Rails before_update嵌套属性回调
问题描述:
我有两个模型(让我们打电话然后A
和B
)。Rails before_update嵌套属性回调
A
has_many
b
s和B
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
集。
由于这关系被一个嵌套形式上使用,即从before_update
如果B
我更新属性形式B
才会被调用。如果我只更改A
的值表示回调未被调用。
当A
更新时,我怎么能拨打B
的before_update
?
在此先感谢。
答
对于属于关联,你可以使用touch
选项:
class B < ApplicationRecord
belongs_to :a, inverse_of: :bs, touch: true
end
当你更新B. 这将更新a.updated_at
但是这个选项不适用于has_many
关系存在,因为它可能有潜在的灾难性后果表现(如果一个A有1000个或更多的Bs)。从你需要做这样的事情的时候要非常小心比例的角度来看
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
:
但是,您可以滚你自己。写操作很昂贵,通常你可以通过代理或使用连接来解决这个问题。 – max
非常感谢,马克斯。 – ThalesMiguel