嵌套属性update_attributes使用insert而不是update

时间:2012-03-30 13:36:09

标签: ruby-on-rails nested-attributes update-attributes

我有一个用户和嵌套的配置文件类,如下所示:

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

有谁知道为什么更新会以这种方式发生?我不希望最终得到一个没有连接到任何用户的配置文件行数据库。

4 个答案:

答案 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;修复了它。是的,但我认为它仍然是一个错误。

我想知道上述症状是否也适用于您的情况,以确认这是一个错误。