Skip to content

Instantly share code, notes, and snippets.

@waseem
Created April 1, 2011 09:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save waseem/897939 to your computer and use it in GitHub Desktop.
Save waseem/897939 to your computer and use it in GitHub Desktop.
Parameters: { "listing_services_attributes"=>{"0"=>{"service_attributes"=>{"name"=>"Fruits", "id"=>"6274"}}, "1"=>{"service_attributes"=>{"name"=>"Mocha"}}, "2"=>{"service_attributes"=>{"name"=>"Mocha"}}, "3"=>{"service_attributes"=>{"name"=>""}}, "4"=>{"service_attributes"=>{"name"=>""}}}}
Admin Load (0.1ms) SELECT `users`.* FROM `users` WHERE (`users`.`type` = 'Admin') AND (`users`.`id` = 3) LIMIT 1
Category Load (0.3ms) SELECT `categories`.* FROM `categories` WHERE (categories.category_id IS NULL) ORDER BY name ASC
Category Load (0.4ms) SELECT `categories`.* FROM `categories` WHERE (`categories`.category_id IN (1,40,182,244,26,306,330,12,60,75,206,135,195,260,318,341,8,70,87,163,288,324)) ORDER BY name ASC
Location Load (0.2ms) SELECT `locations`.* FROM `locations`
Location Load (0.1ms) SELECT `locations`.* FROM `locations` WHERE (`locations`.`name` = 'Agege') LIMIT 1
Completed in 1272ms
ActiveRecord::RecordNotFound (Couldn't find Service with ID=6274 for ListingService with ID=):
activerecord (3.0.1) lib/active_record/nested_attributes.rb:413:in `raise_nested_attributes_record_not_found'
activerecord (3.0.1) lib/active_record/nested_attributes.rb:299:in `assign_nested_attributes_for_one_to_one_association'
activerecord (3.0.1) lib/active_record/nested_attributes.rb:254:in `service_attributes='
activerecord (3.0.1) lib/active_record/base.rb:1548:in `block in attributes='
activerecord (3.0.1) lib/active_record/base.rb:1544:in `each'
activerecord (3.0.1) lib/active_record/base.rb:1544:in `attributes='
activerecord (3.0.1) lib/active_record/base.rb:1411:in `initialize'
vendor/plugins/active_scaffold/lib/extensions/active_association_reflection.rb:10:in `new'
vendor/plugins/active_scaffold/lib/extensions/active_association_reflection.rb:10:in `build_association'
activerecord (3.0.1) lib/active_record/associations/association_collection.rb:512:in `build_record'
class Listing < ActiveRecord::Base
...
has_many :listing_services, :dependent => :destroy
has_many :services, :through => :listing_services
accepts_nested_attributes_for :listing_services
...
end
class ListingService < ActiveRecord::Base
...
belongs_to :listing
belongs_to :service
accepts_nested_attributes_for :service
...
end
class ListingsController < ApplicationController
def new
@listing = Listing.new
3.times do
listing_service = @listing.listing_services.build
listing_service.service = Service.new
end
end
def create
listing = Listing.new(params[:listing])
if listing.save
... # Success
else
... # Failure
end
end
end
<%= form_for(@listing) do |f| %>
...
<% listing_number = 0 %>
<%= f.fields_for :listing_services do |ls| %>
<% listing_number += 1 %>
<%= ls.fields_for :service do |service_form| %>
<tr>
<td><%= service_form.label(:name, 'Product/Service ' + listing_number.to_s) %></td>
<td>
<%= service_form.text_field(:name) %><%= service_form.error_message_on :name %>
<%= service_form.hidden_field(:id) %>
<div class="auto_complete" id ="listing_listing_services_attributes_<%= listing_number - 1 %>_service_attributes_name_auto_complete"></div>
<%= auto_complete_field "listing_listing_services_attributes_#{listing_number - 1}_service_attributes_name", :url => services_for_autocomplete_services_path, :param_name => "service_attr_name", :min_chars => 2,
:after_update_element => "function (field, element) {
updateId('listing_listing_services_attributes_#{listing_number - 1}_service_attributes_id',
element
);
}" %>
</td>
</tr>
<% end %>
<% end %>
...
<% end %>
# updateId() updates the id field of a service when user selects a service in autosuggest
class Service < ActiveRecord::Base
...
has_many :listing_services, :dependent => :destroy
has_many :listings, :through => :listing_services
...
end
@Satish
Copy link

Satish commented Apr 3, 2011

First of all use

accepts_nested_attributes_for :services

instead of

accepts_nested_attributes_for :listing_services

And it is clear from "ActiveRecord::RecordNotFound (Couldn't find Service with ID=6274 for ListingService with ID=):"

That there is no service with D=6274

@brandentanga
Copy link

Note: Part of my post looks wonky. Sorry about that.

I'm running into the same error. Judging from the params hash, you are attempting to create a new record (ListingService), while simultaneously associating it with a different existing record (Service). This behavior works in Rails 2.3., but does not in Rails 3.0.

From my Rails 2 app's script/console:
User.new("problems_attributes"=>{"0"=>{"name"=>"test problem", "id"=>"5"}})

<User id: nil, created_at: nil, updated_at: nil.........

From my upgraded Rails 3 app's rails console:
User.new("problems_attributes"=>{"0"=>{"name"=>"test problem", "id"=>"5"}})
ActiveRecord::RecordNotFound: Couldn't find Problem with ID=5 for User with ID=
from /Library/Ruby/Gems/1.8/gems/activerecord-3.0.3/lib/active_record/nested_attributes.rb:418:in `raise_nested_attributes_record_not_found'........

A possible hack to fix this is to edit the params hash before it gets sent to the server, so that ActiveRecord doesn't automatically pick up the nested model, then parsing this nested model yourself and doing the necessary actions in your controller. However, that seems like a lot of unnecessary work.

My guess is that the behavior of accepts_nested_attributes_for has changed in Rails 3, and there may be a setting which we are not aware of that is defaulted to false.

@brandentanga
Copy link

Some further googling has led me to believe that this behavior has been changed on purpose for any version of rails >= 3.0.1

http://stackoverflow.com/questions/3783247/deeply-nested-rails-forms-using-belong-to-not-working
https://rails.lighthouseapp.com/projects/8994/tickets/6314-accepts_nested_attributes_for
http://groups.google.com/group/rubyonrails-security/browse_thread/thread/f9f913d328dafe0c

Of course now we are kinda stuck because if we have the case described above, we cannot use the params hash as provided by the form builder.

@waseem
Copy link
Author

waseem commented Apr 17, 2011

@brandentanga To solve above problem, right now I am following the first solution mentioned by you. I am manipulating the params hash in my controller before it is passed to ActiveRecord and accepts_nested_attributes_for. Right now, this seems to be the only good enough solution to me.

@ndemoreau
Copy link

Hi guys, no update on this? I'm running into the same issue. Solving it as well by manipulating params. But it's not very clean... I would expect better solution from rails

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment