Ruby on rails 如何使用回调设计相互依赖的模型

Ruby on rails 如何使用回调设计相互依赖的模型,ruby-on-rails,activerecord,model,callback,rails-activerecord,Ruby On Rails,Activerecord,Model,Callback,Rails Activerecord,所以我有两种型号A和B 保存或销毁A时,需要根据A发生的情况更新B 保存或销毁B时,需要根据B发生的情况更新A 我不能只放两个回调,它会导致模型递归地回调。当模型A由于触发B回调而保存时,我不需要启动回调,反之亦然 rails是如何做到这一点的?您可以在回调中使用update\u列: e、 g: 模型A已保存。在回调中,您有如下内容: recordB.update_columns(:name => '') update_列将不会运行任何回调。 注意:它也不会运行验证,也不会更新更新的_a

所以我有两种型号
A
B

保存或销毁
A
时,需要根据
A
发生的情况更新
B

保存或销毁
B
时,需要根据
B
发生的情况更新
A

我不能只放两个回调,它会导致模型递归地回调。当模型
A
由于触发
B
回调而保存时,我不需要启动回调,反之亦然


rails是如何做到这一点的?

您可以在回调中使用
update\u列

e、 g:

模型A已保存。在回调中,您有如下内容:

recordB.update_columns(:name => '')
update_列将不会运行任何回调。
注意:它也不会运行验证,也不会更新更新的_at字段。

我也遇到过类似的情况,最好在回调中使用标志

class A
  attr_accessor :is_updated_by_callback
  after_commit :update_b

  def update_b
    return if is_updated_by_callback
    b.is_updated_by_callback = true
    b.update
  end 
end

反之亦然,除非我需要验证和其他不相关的回调才能正常工作。所以我想没有更好的办法了……丑陋?我不知道那是什么意思。也许在过去15年中,随着框架的激增,我们不得不忘记标志,但它通常是有用的。有一点乐趣,搜索你的宝石来源的“国旗”,你可能会感到惊讶。无论如何,如果你找到一个更好的解决方案,请告诉我。例如,为了正确地执行操作,我必须重置读取它的回调中的标志,如果有多个消费者回调,则会变得复杂。我同意标志是一件非常普通的事情。您不必重置标志,因为它不会保存在数据库中,这要归功于
attr\u accessor
。如果您有多个回调可能同时触发,那么如果我想重用模型实例(同意这是一个罕见的情况,可能是一个糟糕的设计决策),那么您可以使用位标志而不是布尔值-我必须重置,因为否则我会得到不需要的回调跳过。我明白了。实际上,您需要对回调进行更复杂的设计,因为Rails并没有像您在activesupport/lib/active_support/callbacks.rb#run_回调中看到的那样针对这种情况进行设计。也许您可以使用
Kernel.caller
来验证该操作是否由回调触发——但这种技术进入了我对
aughous
的定义中,因为我们依赖于rails的内部结构,这些内部结构将来可能会发生变化