Rails before_update 具有嵌套属性的回调

Rails before_update callback with nested attributes

我有两个模型(让我们调用 AB)。

Ahas_manybBbelongs_toA.

class A < ApplicationRecord
  has_many :bs, dependent: :destroy, inverse_of: :a
  accepts_nested_attributes_for :bs, reject_if: :all_blank, allow_destroy: true
  validates_associated :bs
end


class B < ApplicationRecord
  belongs_to :a, inverse_of: :bs
  before_update :do_something, unless: Proc.new { |b| b.a.some_enum_value? if a }

  def do_something
    self.some_field = nil
  end

end

除此之外,B 有一个 before_update 回调将 some_field 设置为零 if Asome_enum_value设置.

由于此关系用于 嵌套形式 ,因此仅当我更新属性形式 [=14] 时才会调用 B 中的 before_update =].如果我只更改值形式 A,则不会调用该回调。

如何在 A 更新时调用 Bbefore_update

提前致谢。

对于属于协会,您可以使用 touch 选项:

class B < ApplicationRecord
  belongs_to :a, inverse_of: :bs, touch: true
end

当您更新 B 时,它会更新 a.updated_at。 然而,此选项对于 has_many 关系不存在,因为它可能具有潜在的灾难性性能后果(如果 A 有 1000 或更多 B)。

但是您可以自己滚动:

class A < ApplicationRecord
  has_many :bs, dependent: :destroy, inverse_of: :a
  accepts_nested_attributes_for :bs, reject_if: :all_blank, allow_destroy: true
  validates_associated :bs
  after_update :cascade_update!

  def cascade_update!
    # http://api.rubyonrails.org/classes/ActiveRecord/Batches.html#method-i-find_each
    bs.find_each(batch_size: 100) do |b|
      b.update!(updated_at: Time.zone.now)
    end
  end
end