I'm working on a messy form which among other things has to manage a section with two-level nesting. It's almost working, but there's a snag and the only thing I can see that's different from other deeply-nested forms that work is that there's a belongs_to relationship rather than has_many. Here are the models:
Event
has_many :company_events, :dependent => :destroy
accepts_nested_attributes_for :company_events
CompanyEvent
belongs_to :company
accepts_nested_attributes_for :company, :update_only => true
belongs_to :event
belongs_to :event_type
Company
has_many :company_events
has_many :events, :through => :company_events
So it's a fairly standard many-to-many relationship via a link table, company_events. The form in question is creating/editing an event, with a dynamic "Add Company" Javascript button, all pretty much based on Ryan Bates' screencast and GitHub repo.
The main form:
<table id="companies">
<tr><th>Company Name</th></tr>
<% f.fields_for :company_events do |builder| %>
<%= render 'company_event_fields', :f => builder, :f_o => nil %>
<% end -%>
</table>
<p><br/><%= link_to_add_fields "Add Company", f, :company_events, "events" %></p>
And the included form is as follows. An important thing to note is that the company ID is set via a Javascript update, which I won't include here because it's long. Basically the user starts typing a name, an autocomplete list is displayed, and clicking on the name sets both the company name and the id in the form.
<tr class="company_event_fields">
<td>
<% f.fields_for(:company) do |company_form| -%>
<%= company_form.text_field :name, :size => 80 %>
<%= company_form.hidden_field :id %>
<% end -%>
</td>
<td>
<%= f.hidden_field :_destroy %>
<%= link_to_function "remove", "remove_co_fields(this)" %>
</td>
</tr>
When I update an existing record, everything works just fine. When I try to save the form with a newly-created record, though, I get:
ActiveRecord::RecordNotFound in EventsController#update
Couldn't find Company with ID=12345 for CompanyEvent with ID=
With the stacktrace:
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/nested_attributes.rb:401:in `raise_nested_attributes_record_not_found'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/nested_attributes.rb:289:in `assign_nested_attributes_for_one_to_one_association'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/nested_attributes.rb:244:in `company_attributes='
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/base.rb:2906:in `send'
I've looked through the code in nested_attributes, and run through it with a debugger. What's happening seems to be that because there's a Company.id, ActiveRecord is assuming that there is already an entry, but then of course it doesn't find one. This seems very odd, since obviously I'd need to pass in an ID in order to create a new CompanyEvent entry. So, I'm guessing that I'm missing something.
The examples I've found that work all seem to be nested using has_many relationships all the way down, while in this case it's a belongs_to, and I'm wondering if that's the root of the problem. Any ideas would be greatly appreciated...
Here's another possible solution that I posted in a similar question: https://stackoverflow.com/a/12064875/47185
Something like this...
accepts_nested_attributes_for :company
def company_attributes=(attributes)
if attributes['id'].present?
self.company = Company.find(attributes['id'])
end
super
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With