37

我已经浏览了 Rails 源代码一段时间了,我认为除了以下之外没有更好的方法来获取所有回调的列表:ActiveRecord::Callbacks::CALLBACKS- 这是一个常量列表。

这意味着如果您使用的是像 devise_invitable 这样的 gem,它添加了一个:invitation_accepted用分数调用的新回调:after:before然后ActiveRecord::Callbacks::CALLBACKS将不起作用。

除了打开 rails 模块并确保每个模型类都有一个内部回调列表之外,您是否知道一个简单的修复方法?

4

6 回答 6

51

您可以调用Model._save_callbacks以获取保存时所有回调的列表。然后,您可以将其过滤为您需要的类型,例如:before:after像这样:

Model._save_callbacks.select {|cb| cb.kind == :before}

Model._destroy_callbacks对等工作相同。

于 2013-01-15T09:33:58.863 回答
20

文档说“总共有 19 个回调”......但他们似乎并没有说出这 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
于 2013-12-18T08:29:48.987 回答
3

请注意,如果您只是想触发回调,则可以使用该#run_callbacks(kind)方法:

o = Order.find 123 # Created with SQL
o.run_callbacks(:create)
o.run_callbacks(:save)
o.run_callbacks(:commit)
于 2013-09-25T15:49:14.557 回答
3

如果您在该._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)
于 2015-12-24T18:12:37.003 回答
1

我将提出最通用的解决方案。

即使 gem 声明自定义回调(例如偏执狂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-------
于 2018-11-30T20:28:28.940 回答
0

对于after_commit回调,调用Model._commit_callbacks.

但是请注意,Rails 中存在一个已知错误(Rails 5.2.2 中仍然存在),即after_commit回调不是按照它们在模型中声明的顺序运行的,即使它们在该_commit_callbacks调用中以正确的顺序出现也是如此。

更多信息:多个 after_commit 回调(Rails)的执行顺序https://github.com/rails/rails/issues/20911

于 2020-02-24T21:43:34.647 回答