我有一个用户和嵌套的配置文件类,如下所示:
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
我不明白rails为什么要抛弃旧的配置文件,创建一个新的配置文件。
使用
user.profile.update_attributes({name: 'some name'})
只是按预期更新当前配置文件。但在这种情况下,我不会利用的accepts_nested_attributes_for
有人知道为什么更新会这样吗?我不希望最终出现一个没有连接到任何用户的配置文件行数据库。
对于在Rails4:fields_For中遇到相同问题的每个人来说,已经为嵌套表单添加了id,但必须允许使用:id参数。我只允许使用一个:object_name_id参数,因为这不会引发任何错误,所以我花了一些时间才在服务器日志中看到它。希望这能帮助比我在这方面浪费更少的时间:)
如果检查表单,则需要在Profile对象的嵌套属性哈希中设置id属性。如果没有设置id,那么ActiveRecord会假定它是一个新对象。
例如,如果您有一个ERB表单为用户中的嵌套配置文件构建了一组带有嵌套"profile_attributes"参数哈希的"用户"参数,那么您可以为配置文件id包含一个隐藏值,如下所示:
<%= hidden_field "user[profile_attributes][id]", @profile.id %>
我通过添加update_only
选项解决了这个问题:
accepts_nested_attributes_for :profile, update_only: true
现在,只有在不存在新配置文件的情况下,才会创建新配置文件。
我在Rails的另一个版本中遇到了这个问题,我想我会失去理智的。虽然添加update_only=>true解决了这个问题,但我认为这是Rails中的一个错误。
在我的案例中,症状是:我会删除belongs_to并创建新的嵌套对象的关联,直到我第一次刷新页面。之后它就正常工作了。
在我的例子中,我在嵌套类中添加了一个before_save方法,并打印它保存的内容。在调用update_attributes之前,我还打印了这些属性。他们正确设置了"parent_id"。我还在表单中包含了隐藏的id字段,没有任何更改——这很正常,因为它已经通过使用fields_for。。。
令人惊讶的是:我看到一个更新调用生成了两个保存调用。第一次保存将具有嵌套的对象id,但belongs_to id为null。因此,这将更新记录,将"parent_id"设置为null。第二个保存将设置"parent_id",但它将嵌套的对象id设置为null。
正如我所说,我通过添加update_only=>true来修复它,但我认为它仍然是一个bug。
我想知道以上症状是否也适用于您的病例,以确认这是一个错误。