我一直在浏览rails源一段时间了,我认为除了ActiveRecord::Callbacks::CALLBACKS
之外还有更好的方法来获取所有回调列表 - 这是一个不变的清单。
这意味着如果您使用像devise_invitable这样的gem,会添加一个名为:invitation_accepted
的新回调,其得分为:after
,而:before
则ActiveRecord::Callbacks::CALLBACKS
将无效。
除了打开rails模块并确保每个模型类的内部回调列表之外,您是否知道一个简单的修复方法?
答案 0 :(得分:45)
您可以致电Model._save_callbacks
获取保存时所有回调的列表。
然后,您可以将其过滤到您需要的类型,例如:before
或:after
就像这样:
Model._save_callbacks.select {|cb| cb.kind == :before}
适用于Model._destroy_callbacks
等。
答案 1 :(得分:20)
docs说“总共有十九个回调”......但他们似乎并没有说这19个实际上是什么!
对于那些使用Google搜索“所有ActiveRecord回调列表”的人,就像我一样,这里是列表(通过使用问题中描述的ActiveRecord::Callbacks::CALLBACKS
找到):
:after_initialize
:after_find
:after_touch
:before_validation
:after_validation
:before_save
:around_save
:after_save
:before_create
:around_create
:after_create
:before_update
:around_update
:after_update
:before_destroy
:around_destroy
:after_destroy
:after_commit
:after_rollback
答案 2 :(得分:3)
请注意,如果您只是想触发回调,可以使用#run_callbacks(kind)
方法:
o = Order.find 123 # Created with SQL
o.run_callbacks(:create)
o.run_callbacks(:save)
o.run_callbacks(:commit)
答案 3 :(得分:2)
如果您在._save_callbacks
方法之前使用Rails版本,则可以使用以下内容:
# list of callback_chain methods that return a CallbackChain
Model.methods.select { |m| m.to_s.include? "callback" }.sort
# get all methods in specific call back chain, like after_save
Model.after_save_callback_chain.collect(&:method)
答案 4 :(得分:0)
我将提出最通用的解决方案。
即使在gem声明自定义回调(例如paranoia和after_real_destroy
列出所有回调
Model.methods.select { |m| m.to_s.include? "callback" }.sort
然后,如果您键入方法名称,则可以得到给定的回调。
Model._update_callbacks
Model._real_destroy_callbacks
Model._destroy_callbacks
如果您列出了所有回调,那么您可以通过检查@filter
实例变量来找到所需的回调。
require 'pp'
Activity._destroy_callbacks.each_with_index { |clbk,index| puts "#{index}-------\n#{clbk.pretty_inspect}" } ; nil
# [...]
#<ActiveSupport::Callbacks::Callback:0x00007ff14ee7a968
@chain_config=
{:scope=>[:kind, :name],
:terminator=>
#<Proc:0x00007ff13fb825f8@/Users/mypc/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/activemodel-4.1.16/lib/active_model/callbacks.rb:103 (lambda)>,
:skip_after_callbacks_if_terminated=>true},
@filter=
#<Proc:0x00007ff14ee7ac10@/Users/mypc/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/activerecord-4.1.16/lib/active_record/associations/builder/association.rb:135 (lambda)>,
@if=[],
@key=70337193825800,
@kind=:before,
@name=:destroy,
@unless=[]>
4-------
#<ActiveSupport::Callbacks::Callback:0x00007ff14ee3a228
@chain_config=
{:scope=>[:kind, :name],
:terminator=>
#<Proc:0x00007ff13fb825f8@/Users/mypc/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/activemodel-4.1.16/lib/active_model/callbacks.rb:103 (lambda)>,
:skip_after_callbacks_if_terminated=>true},
@filter=:audit_destroy,
@if=[],
@key=:audit_destroy,
@kind=:before,
@name=:destroy,
@unless=[]>
5-------
答案 5 :(得分:0)
对于after_commit
回调,请调用Model._commit_callbacks
。
但是请注意,Rails中存在一个已知的错误(仍在Rails 5.2.2中存在),after_commit
回调的执行并未按照在模型中声明的顺序运行,即使它们出现在模型中也很困难。 _commit_callbacks
调用中的正确顺序。
更多信息:Execution order of multiple after_commit callbacks (Rails)和https://github.com/rails/rails/issues/20911