我有一个用户和嵌套的配置文件类,如下所示:
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
有谁知道为什么更新会以这种方式发生?我不希望最终得到一个没有连接到任何用户的配置文件行数据库。
答案 0 :(得分:35)
对于在Rails 4中遇到相同问题的每个人:fields_for已经为您的嵌套表单添加了id,但您必须允许:id参数。我只允许:object_name_id参数,因为这不会引发任何错误,所以我花了一些时间才在服务器日志中看到这个。希望这有助于某人浪费时间比我更少:)
答案 1 :(得分:23)
如果检查表单,则需要在Profile对象的嵌套属性哈希中设置id属性。如果未设置id,则ActiveRecord假定它是一个新对象。
例如,如果您有一个ERB表单构建一组'user'参数,其中嵌套的'profile_attributes'参数哈希用于用户中的嵌套配置文件,您可以为配置文件ID包含一个隐藏值,如下所示:
<%= hidden_field "user[profile_attributes][id]", @profile.id %>
答案 2 :(得分:19)
我通过添加update_only
选项解决了这个问题:
accepts_nested_attributes_for :profile, update_only: true
现在只有在尚未存在的情况下才会创建新的个人资料。
答案 3 :(得分:0)
我在另一个版本的Rails中遇到了这个问题,我想我会失去理智。 添加update_only =&gt;时真的解决了我认为这是Rails中的一个错误。
在我的情况下的症状:我将获得与belongs_to删除和创建的新嵌套对象的关联 - 直到我第一次刷新页面。之后它运作正常。
在我的情况下,我在我的嵌套类中添加了一个before_save方法并打印了它保存的内容。 我还在调用update_attributes之前打印了属性。他们有'#34; parent_id&#34;设置正确。 我还在表单中包含了隐藏的id字段,没有更改 - 这是正常的,因为它已经包含在使用fields_for ...
惊喜:我看到一个更新调用生成两个保存调用。 第一次保存将具有嵌套对象id,但对于belongs_to id,则为null。 - 所以这会更新记录以设置&#34; parent_id&#34;为空。 第二次保存将包含&#34; parent_id&#34; set,但它将嵌套对象id设置为null。
正如我所说,我通过添加update_only =&gt;修复了它。是的,但我认为它仍然是一个错误。
我想知道上述症状是否也适用于您的情况,以确认这是一个错误。