归属触摸:true不会在association.build和嵌套属性分配上触发

ulf*_*rts 4 ruby ruby-on-rails rails-activerecord ruby-on-rails-5

OpenProject应用程序中,我们有两个模型:

CustomField

class CustomField < ActiveRecord::Base
  has_many :custom_options, -> { order(position: :asc) }, dependent: :delete_all
  accepts_nested_attributes_for :custom_options
  ...
end
Run Code Online (Sandbox Code Playgroud)

CustomOption

class CustomOption < ActiveRecord::Base
  belongs_to :custom_field, touch: true
  ...
end
Run Code Online (Sandbox Code Playgroud)

然后,在自定义字段控制器中,我们通过批量分配修改自定义字段的选项并保存记录:

@custom_field.attributes = get_custom_field_params

if @custom_field.save 
  ...
Run Code Online (Sandbox Code Playgroud)

由于我touch: truecustom_field关联中进行了配置,因此CustomOption我希望自定义字段的updated_at属性在此时进行更新,但是这不会发生。该日志未显示任何类似于的SQL请求UPDATE custom_fields SET update_at = ....。无论是添加自定义选项还是修改自定义选项,对自定义选项本身所做的更改都将正确保留。

调试显示:

  • 使用时的相同错误行为custom_field.custom_options.build及后续custom_field.save
  • 使用时的预期行为 custom_field.custom_options.create
  • 使用时的预期行为 CustomOption.create custom_field: x
  • 使用时的预期行为 custom_field.custom_option[x].destroy

我知道我可以通过定义after_save回调来解决此问题,但是这种行为确实让我感到意外,因为这是意外的。

是否期望并记录了上述行为?如果是这样,我在哪里可以找到此信息?

chu*_*off 7

问题是,如果父模型具有任何after_commit回调(可能还有其他回调),则:touch在自动保存关联记录时将停止工作,即使该回调没有执行任何操作。

您的CustomField模型有after_commit来自acts_as_listgem的回调。这打破了:touch

存在类似的问题https://github.com/rails/rails/issues/26726。该问题与关联accepts_nested_attributes_for,但我确信accepts_nested_attributes_for至少与您无关。

由问题作者(@ulferts)添加:

定义inverse_of: 'custom_field'custom_options关联CustomField似乎绕过这个问题,原因不明。

has_many :custom_options,
         -> { order(position: :asc) }, 
         dependent: :delete_all,
         inverse_of: 'custom_field'
Run Code Online (Sandbox Code Playgroud)