Reputation: 1763
When upgrading from Rails 3.2 to Rails 5 I ran into this problem where a model suddenly refuses to save.
I have 2 models: ClosingDay
and Location
which have a has_many :through relation via a ClosingDayLocation
model. When creating a ClosingDay
the user needs to select 1 or more Location
records using checkboxes.
However, regardless of which Location
records I select on the form, I always get an error saving the ClosingDay
record telling me that the associated ClosingDayLocation
is invalid because closing_day_id
is empty.
Models:
class ClosingDay < ActiveRecord::Base
has_many :closing_day_locations, :dependent => :destroy
has_many :locations, :through => :closing_day_locations
end
class Location < ActiveRecord::Base
has_many :closing_day_locations, :dependent => :destroy
has_many :closing_days, :through => :closing_day_locations
end
class ClosingDayLocation < ActiveRecord::Base
belongs_to :location
belongs_to :closing_day
validates :closing_day_id, :presence => true
validates :location_id, :presence => true
end
Controller
def create
@closing_day = ClosingDay.build(closing_day_params)
if @closing_day.save
redirect_to(closing_days_url, :notice => 'OK')
else
@locations = Location.active.order(:name)
render :action => 'new'
end
end
private
def closing_day_params
params.require(:closing_day).permit(:date, :name, location_ids: [])
end
Form
<%= form_for(@closing_day) do |f| %>
<%= show_errors_for(@closing_day) %>
<table>
<tr>
<td><%= f.label :name %></td>
<td><%= f.text_field :name %></td>
</tr>
<tr>
<td><%= f.label :date %></td>
<td><%= f.text_field :date %></td>
</tr>
<tr>
<td><%= label_tag 'closing_day[location_ids][]', 'Locations' %></td>
<td>
<%= hidden_field_tag 'closing_day[location_ids][]', nil %>
<% @locations.each do |location| %>
<p>
<%= label_tag do %>
<%= check_box_tag 'closing_day[location_ids][]', location.id, @closing_day.location_ids.include?(location.id) %>
<%= location.name %>
<% end %>
</p>
<% end %>
</td>
</tr>
<tr>
<td colspan="2"><%= f.submit %></td>
</tr>
</table>
<% end %>
So in short, I want to create a new @closing_day
record and assign associated (pre-existing) locations by assigning Location
IDs using @closing_day.location_ids = [3,6,9]
essentially. This works in Rails 3.2 but does not seem to work in Rails 5.
What is the best way to still keep this functionality? I have also tried adding accepts_nested_attributes_for :locations, :allow_destroy => true
and accepts_nested_attributes_for :closing_day_locations, :allow_destroy => true
but that does not seem to work. The associated ClosingDayLocation
models seem to be created, but the closing_day_id
remains empty, resulting in an error.
Upvotes: 1
Views: 1478
Reputation: 1763
After some more tinkering I found the problem and solved it. I'll share it here in case others run into the same issues!
class ClosingDayLocation < ActiveRecord::Base
belongs_to :location
belongs_to :closing_day
#validates :closing_day_id, :presence => true
#validates :location_id, :presence => true
end
After removing those 2 validations on the intermediate model it worked fine for both creating and updating. Apparently some ordering in validating and saving associated records has shifted around between Rails 3.2 and Rails 5.
Upvotes: 1