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

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

class User < ActiveRecord::Base has_one :profile attr_accessible :profile_attributes accepts_nested_attributes_for :profile end class Profile  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

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

对于在Rails 4中遇到相同问题的每个人:fields_for已经为您的嵌套表单添加了id,但您必须允许:id参数。 我只允许:object_name_id参数,因为这不会引发任何错误,所以我花了一些时间才在服务器日志中看到这个。 希望这有助于有人浪费时间比我少:)

如果检查表单,则需要在Profile对象的嵌套属性哈希中设置id属性。 如果未设置id,则ActiveRecord假定它是一个新对象。

例如,如果您有一个ERB表单构建一组’user’参数,其中嵌套的’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中的某个bug。

在我的情况下的症状:我将获得与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来修复它,但我认为它仍然是一个错误。

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