form selection- nested attributes

I am working on my first rails project using rails 4.1x and cocoon for nested forms,and formtastic . I am not sure if my problem is just form related or also a problem with models.

A ‘user’ adds 1 or more ‘entries.’ Each entry has 1 or more ‘rides’. Each ride can have only 1 ‘horse’ . A horse will be related to many rides. Saving and retrieving the related horse in create and edit forms is my problem.

My form currently saves entry (date), ride (test), and new horse (via cocoon link_to_add_association) correctly. My ability to select existing horses for new rides or for editing is not working.

Right now my new entry does not have existing horse select available when I click to add ride. I can only add new horse. When editing an existing horse, existing horse select shows select with horse name and id, but does mark existing value as selected. It saves incorrect names/ids to params so really the line in view is a placeholder to place correct select code.

params on new entry create with new horse:

{“utf8”=>“√”, “authenticity_token”=>“xxxx=”, “entry”=>{“show_date”=>“2014/10/26”, “rides_attributes”=>{“1408889669745”=>{“test”=>“Intro B”, “horse_attributes”=>{“name”=>“aa”}}}}, “commit”=>“Create Entry”, “action”=>“create”, “controller”=>“entries”}

attempting to edit same entry attempts to set name to id of previous horse. I have tried many variations on select but have not figured it out :

{“utf8”=>“√”, “_method”=>“patch”, “authenticity_token”=>“xxxx=”, “entry”=>{“show_date”=>“2014/10/26”, “rides_attributes”=>{“0”=>{“test”=>“Intro B”, “horse_attributes”=>{“name”=>“43”, “id”=>“44”}, “id”=>“72”}}}, “commit”=>“Update Entry”, “action”=>“update”, “controller”=>“entries”, “id”=>“75”}

In my views:

_form.html.haml:

= semantic_form_for @entry do |f|

= f.inputs do

= f.input :show_date, :as => :select, :collection => [‘2014/08/03’, ‘2014/09/14’, ‘2014/10/26’, ‘2014/11/15’]

%h3 Rides

#rides

= f.semantic_fields_for :rides do |ride|

= render ‘ride_fields’, :f => ride

.links

= link_to_add_association ‘add ride’, f, :rides

= f.actions do

= f.action :submit

_ride_fields.html.haml:

.nested-fields

= f.inputs do

= f.label :test, “Test”

= f.input :test, :as => :select, :collection => [[‘Intro A’, ‘Intro A’], [‘Intro B’, ‘Intro B’], [‘Intro C’, ‘Intro C’]]

#shows existing horses to choose

= if !@horses.empty?

= f.semantic_fields_for :horse do |horse|

= horse.input :name, :as => :select, :collection => @horses

-# shows new horse form elements immediately if user has no horses

= if @horses.empty?

= f.semantic_fields_for :horse do |horse|

= render ‘horse_fields’, :f => horse

.links

= link_to_add_association ‘add new horse’, f, :horse

partial entries_controller:

class EntriesController < ApplicationController

before_action :set_entry, only: [:show, :edit, :update, :destroy]

before_filter :set_horses, :except => [:destroy, :index]

def new

@user=current_user

@entry = current_user.entries.new

end

def create

@entry = current_user.entries.new(entry_params)

respond_to do |format|

if @entry.save

format.html { redirect_to @entry, notice: 'Entry was successfully created.' }

format.json { render :show, status: :created, location: @entry }

else

format.html { render :new }

format.json { render json: @entry.errors, status: :unprocessable_entity }

end

end

end

def update

respond_to do |format|

if @entry.update(entry_params)

format.html { redirect_to @entry, notice: ‘Entry was successfully updated.’ }

format.json { render :show, status: :ok, location: @entry }

else

format.html { render :edit }

format.json { render json: @entry.errors, status: :unprocessable_entity }

end

end

end

private

Use callbacks to share common setup or constraints between actions.

def set_entry

@entry = Entry.find(params[:id])

end

Never trust parameters from the scary internet, only allow the white list through.

def entry_params

  params.require(:entry).permit(:show_date, rides_attributes: [:id, :test,  :_destroy, horse_attributes: [:name, :id]] )

end

def set_horses

id = current_user[:id]

if current_user.admin?

@horses=Horse.all

else

@horses = current_user.horses

end

end

end

my models:

class Entry < ActiveRecord::Base

belongs_to :user

has_many :rides, :dependent => :destroy

has_many :horses, :through => :rides, :dependent => :destroy

accepts_nested_attributes_for :rides, :reject_if => lambda { |a| a[:test].blank? }, :allow_destroy => true

accepts_nested_attributes_for :horses #, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true

validates_presence_of :show_date

end

class Ride < ActiveRecord::Base

belongs_to :entry, inverse_of: :entry

belongs_to :horse

belongs_to :user, inverse_of: :user

accepts_nested_attributes_for :horse

end

class Horse < ActiveRecord::Base

has_many :rides

belongs_to :user, :dependent => :destroy

end

Incidentally, as I type this question I realized another problem I will have once it works:

I can add more than one ride to each entry. The second ride, for example, could have the same horse again but it has not yet been created until this form is submitted to create the entry. How can I add horse to db immediately, without leaving this entry form so that horse is available for next added ride?

I will also need to hide existing horses select if user opts to add new (however I think this may be covered in cocoon docs or howto)