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

Jas*_*son 28 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
Run Code Online (Sandbox Code Playgroud)

我不明白为什么rails会丢弃旧配置文件并创建一个新配置文件.

运用

user.profile.update_attributes({name: 'some name'})
Run Code Online (Sandbox Code Playgroud)

只是按预期更新当前配置文件.但在那种情况下,我没有利用accepts_nested_attributes_for

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

irr*_*ncu 37

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

  • 我发现将`config.action_controller.action_on_unpermitted_pa​​rameters`改为`:raise`而不是默认的`:log`是有帮助的.当它在你脸上爆炸时调试更容易!https://github.com/rails/strong_parameters#handling-of-unpermitted-keys (5认同)

Win*_*eld 23

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

例如,如果您有一个ERB表单构建一组'user'参数,其中嵌套的'profile_attributes'参数哈希用于用户中的嵌套配置文件,则可以为配置文件ID包含一个隐藏值,如下所示:

<%= hidden_field "user[profile_attributes][id]", @profile.id %>
Run Code Online (Sandbox Code Playgroud)


Jas*_*son 20

我通过添加update_only选项解决了这个问题:

accepts_nested_attributes_for :profile, update_only: true
Run Code Online (Sandbox Code Playgroud)

现在只有在尚未存在的情况下才会创建新的配置文件.

  • 我很确定@Winfield的答案是正确的 (3认同)