Nested attributes with collection_select not saving
In my edit form I simply cannot figure out why collection_select isn’t saving the various values when it's nested. It works fine if I use a {multiple: true} and pull it outside of the fields_for event_types. Am I missing something? I have tried many configurations regarding strong params.. nothing.
Thanks for any assistance.
class Race < ActiveRecord::Base
has_many :race_events, dependent: :destroy
has_many :event_types, through: :race_events
accepts_nested_attributes_for :event_types
end
class EventType < ActiveRecord::Base
belongs_to :discipline
has_many :race_events
has_many :races, through: :race_events
end
class RaceEvent < ActiveRecord::Base
belongs_to :race
belongs_to :event_type
end
class RacesController < ApplicationController
def edit
authorize! :add_details, @race
if @race.links.empty?
@race.links.new
end
end
def update
authorize! :add_details, @race
if @race.update(race_params)
redirect_to …
else
render :edit
end
end
end
private
def race_params
params.require(:race).permit(:name, :description,:event_type_ids => [], event_types_attributes: [:id, :name])
end
Edit View
<%= form_for(@race, ... ) do |f| %>
<%= f.fields_for :event_types do |event| %>
<%= event.collection_select(:id, EventType.all, :id, :name) %> # This displays the collections correctly but they don's save when updated.
<% end %>
...
<% end %>
Are you specifically having trouble saving the records or is the form having trouble rendering?
Started PATCH "/assistants/134-gilbert-event" for ::1 at 2015-03-19 13:36:57 -0700
Processing by AssistantsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"nsJc3ywZCW9hhk7fyY3jZeuwEhTpOQ4IwOxVYUoLRuMplW7bkCnHZgrt024RL0NVa8v6doFaJPjVPcwTc2Hxg==", "race"=>{"name"=>"Gilbert Event", "race_date"=>"2014-11-22", "city"=>"Gilbert", "state"=>"Alabama", "address"=>"", "zipcode"=>"", "country"=>"Australia", "email"=>"director@gilbertevent.org", "phone"=>"", "links_attributes"=>{"0"=>{"website"=>"http://gilbertevent.org", "registration"=>"", "other"=>"", "id"=>"32"}}, "start_time(1i)"=>"2000", "start_time(2i)"=>"1", "start_time(3i)"=>"1", "start_time(4i)"=>"00", "start_time(5i)"=>"00", "price"=>"", "event_types_attributes"=>{"0"=>{"id"=>"2"}, "1"=>{"id"=>"3"}, "2"=>{"id"=>"5"}, "3"=>{"id"=>"6"}}, "headline"=>"", "description"=>""}, "va"=>"employee_11", "commit"=>"Add Race", "id"=>"134-gilbert-event"}
I got it!
Since I was dealing with a has_many through relationship I needed to reorder a few things. I will post it up shortly.
:)
Awesome, glad you got it fixed. I'd love to see the solution as well. Sometimes it is hard to debug those issues.
First thing was organization. In order to achieve my main goal, I had to rethink what I was trying to do first. Needing to create/update new RaceEvents(join Model) for each Race. However for each RaceEvent I needed to display all the options in a collection_select that was populated from EventTypes.
The short of it was to make the join model my nested model form and inside of that fields_for block, add the collection_select. I then needed to make sure those params were accepted so I had to edit my strong params to make reference of the event_type_id in side of the join models attributes. I will display the updated code below.
class Race < ActiveRecord::Base
has_many :race_events, dependent: :destroy
has_many :event_types, through: :race_events
accepts_nested_attributes_for :race_events, allow_destroy: true
end
class EventType < ActiveRecord::Base
has_many :race_events
has_many :races, through: :race_events
accepts_nested_attributes_for :race_events
end
class RaceEvent < ActiveRecord::Base
belongs_to :race
belongs_to :event_type
end
Now for the Strong Params. Notice how in the join model attributes (race_events_attributes) I needed to include :event_type_id. This through me for awhile. It’s needed to make the proper association, seems almost obvious now. But a couple days ago it definitely wasn’t. :P
def race_params
params.require(:race).permit(:name, :description, race_events_attributes: [:id, :price, :summary, :event_type_id, :_destroy] )
end
end
Finally the view. A couple of gotchas here too. On the collection_select it’s not necessary and important not to include the object directly. This seems to cause a bit of confusion (as this is most of the people problems regarding Collection_select on SO)
<%= form_for @race do |f| %>
<%= f.fields_for :race_events do |event| %>
<div>
<%= event.collection_select :event_type_id, EventType.all, :id, :name %>
<%= event.text_area :summary %>
<%= event.text_field :price %>
<%= event.check_box :_destroy %>
<%= event.label :_destroy, “remove event” %>
</div>
<% end %>
<% end %>
At the end of the day, it wasn’t one problem it was an assortment that needed rethinking and refactoring to get working properly.
Hope that clears it up a little for anyone in need. And thanks GoRails team and community for support!
Thanks. Yeah, as you can see and as Chris mentioned it was a bugger of a bug. Hard to nail down what was causing the issue, just took some time.