Rails before_update具有嵌套属性的回调

时间:2017-02-21 19:26:06

标签: ruby-on-rails callback nested nested-forms nested-attributes

我有两个模型(然后调用AB)。

A has_many bB belongs_to A

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设置了A,则some_enum_value设置为nil

由于此关系用于嵌套表单,因此只有在我更新属性表单before_update时才会调用来自B的{​​{1}}。如果我只更改B的值,则不会调用回调。

如果更新A,如何致电B的{​​{1}}?

提前致谢。

1 个答案:

答案 0 :(得分:2)

对于属于关联,您可以使用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.touch
    end
  end
end