I have a user and nested profile class as follows:
class User < ActiveRecord::Base
has_one :profile
attr_accessible :profile_attributes
accepts_nested_attributes_for :profile
end
class Profile < ActiveRecord::Base
belongs_to :user
attr_accessible :name
end
user = User.find(1)
user.profile.id # => 1
user.update_attributes(profile_attributes: {name: 'some name'})
user.profile.id # => 2
I don't understand why rails is throwing away the old profile and creating a new one.
Using
user.profile.update_attributes({name: 'some name'})
just updates the current profile as expected. But in that case I'm not taking advantage of accepts_nested_attributes_for
Does anyone know why the update happens this way? I'd prefer not to end up with a database of profile rows not connected to any user.
If you check your form, you need to set the id attribute within the nested attribute hash for your Profile object. If the id is not set, ActiveRecord assumes it's a new object.
For example, if you had an ERB form building a set of 'user' parameters with a nested 'profile_attributes' parameter hash for the nested profile within the user, you could include a hidden value for the profile id, like this:
I was hit with this in another version of Rails and I thought I will lose my mind. While adding update_only => true solved it I think it is a bug somewhere in Rails.
Symptoms in my case: I would get the association to the belongs_to deleted and new nested object created - until I first refreshed the page. After that it worked correctly.
In my case I added a before_save method to my nested class and printed what it saved. I also printed the attributes before calling update_attributes. They had the "parent_id" set correctly. I also included the hidden id field in the form, no change - which was normal as it was already included by using fields_for...
Surprise: I saw one update call generating two save calls. First save would have the nested object id but null for the belongs_to id. - so this would update the record to set "parent_id" to null. The second save would have the "parent_id" set but it would have the nested object id set to null.
As I said I fixed it by adding update_only => true, but I think it is still a bug.
I would like to find out if the above symptoms apply to your case too to confirm this is a bug.
For everyone who has the same problem in Rails 4: fields_for already adds the id for your nested forms but you have to permit the :id parameter. I only permitted an :object_name_id parameter and since this does not throw any errors it took me some time until i saw this in the server logs. Hopefully this helps someone wasting less time than me on this :)
I solved this problem by adding the
update_only
option:Now a new profile is only created if one does not already exist.