0

我有两个模型(让我们打电话然后AB)。Rails before_update嵌套属性回调

Ahas_manyb s和Bbelongs_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 

除此之外,Bbefore_update回调,设置some_field为零如果Asome_enum_value集。

由于这关系被一个嵌套形式上使用,即从before_update如果B我更新属性形式B才会被调用。如果我只更改A的值表示回调未被调用。

A更新时,我怎么能拨打Bbefore_update

在此先感谢。

回答

2

对于属于关联,你可以使用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 
+2

但是,您可以滚你自己。写操作很昂贵,通常你可以通过代理或使用连接来解决这个问题。 – max

+0

非常感谢,马克斯。 – ThalesMiguel