Nested attribute update_attributes uses insert rather than update

故事扮演 提交于 2019-11-28 22:19:40

问题


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.


回答1:


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 :)




回答2:


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:

<%= hidden_field "user[profile_attributes][id]", @profile.id %>



回答3:


I solved this problem by adding the update_only option:

accepts_nested_attributes_for :profile, update_only: true

Now a new profile is only created if one does not already exist.




回答4:


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.



来源:https://stackoverflow.com/questions/9944065/nested-attribute-update-attributes-uses-insert-rather-than-update

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!