实例公共方法
define_callbacks(*names) 链接
定义对象生命周期中支持回调的事件集。
define_callbacks :validate
define_callbacks :initialize, :save, :destroy
选项
-
:terminator
- 确定何时 before 过滤器将停止回调链,防止调用后续的 before 和 around 回调,以及触发事件。这应为要执行的 lambda。当前对象和回调的结果 lambda 将提供给 terminator lambda。define_callbacks :validate, terminator: ->(target, result_lambda) { result_lambda.call == false }
在此示例中,如果任何 before 验证回调返回
false
,则不会执行任何后续的 before 和 around 回调。默认 terminator 在回调引发
:abort
时停止链。 -
:skip_after_callbacks_if_terminated
- 确定是否应由:terminator
选项终止 after 回调。默认情况下,无论回调链是否终止,都将执行 after 回调。如果:terminator
选项设置为nil
,则此选项无效。 -
:scope
- 指示在将对象用作回调时应执行哪些方法。class Audit def before(caller) puts 'Audit: before is called' end def before_save(caller) puts 'Audit: before_save is called' end end class Account include ActiveSupport::Callbacks define_callbacks :save set_callback :save, :before, Audit.new def save run_callbacks :save do puts 'save in main' end end end
在上述情况下,每当您保存帐户时,都将调用方法
Audit#before
。另一方面define_callbacks :save, scope: [:kind, :name]
将触发
Audit#before_save
。这是通过对给定实例调用#{kind}_#{name}
构建的。在此情况下,“kind”是“before”,而“name”是定义回调的方法。在此上下文中,:kind
和:name
具有特殊含义::kind
指回调类型(before/after/around),而:name
指定义回调的方法。像这样的声明
define_callbacks :save, scope: [:name]
将调用
Audit#save
。
注释
传递给 define_callbacks
的 names
不能以 !
、?
或 =
结尾。
使用相同的 names
多次调用 define_callbacks
将覆盖先前使用 set_callback
注册的回调。
来源:显示 | 在 GitHub 上
# File activesupport/lib/active_support/callbacks.rb, line 940 def define_callbacks(*names) options = names.extract_options! names.each do |name| name = name.to_sym ([self] + self.descendants).each do |target| target.set_callbacks name, CallbackChain.new(name, options) end module_eval <<-RUBY, __FILE__, __LINE__ + 1 def _run_#{name}_callbacks(&block) run_callbacks #{name.inspect}, &block end def self._#{name}_callbacks get_callbacks(#{name.inspect}) end def self._#{name}_callbacks=(value) set_callbacks(#{name.inspect}, value) end def _#{name}_callbacks __callbacks[#{name.inspect}] end RUBY end end
reset_callbacks(name) 链接
移除给定事件的所有已设置的回调。
# File activesupport/lib/active_support/callbacks.rb, line 850 def reset_callbacks(name) callbacks = get_callbacks name self.descendants.each do |target| chain = target.get_callbacks(name).dup callbacks.each { |c| chain.delete(c) } target.set_callbacks name, chain end set_callbacks(name, callbacks.dup.clear) end
set_callback(name, *filter_list, &block) 链接
为给定事件安装回调。
set_callback :save, :before, :before_method
set_callback :save, :after, :after_method, if: :condition
set_callback :save, :around, ->(r, block) { stuff; result = block.call; stuff }
第二个参数指示回调是在事件的:before
、:after
还是:around
中运行。如果省略,则假定为:before
。这意味着上面的第一个示例也可以写成
set_callback :save, :before_method
回调可以指定为命名实例方法的符号;作为 proc、lambda 或块;或作为响应由 define_callbacks
的:scope
参数确定的特定方法的对象。
如果给出了 proc、lambda 或块,则其主体在当前对象的上下文中进行评估。它还可以选择接受当前对象作为参数。
在设置之前和周围的回调按设置的顺序调用;在相反的顺序中调用之后回调。
如果未停止,则周围回调可以从yield
调用中访问事件的返回值。
选项
-
:if
- 一个符号或一组符号,每个符号都命名一个实例方法或一个 proc;只有当它们全部返回 true 值时,才会调用回调。如果给出了 proc,则其主体在当前对象的上下文中进行评估。它还可以选择接受当前对象作为参数。
-
:unless
- 一个符号或一组符号,每个符号都命名一个实例方法或一个 proc;只有当它们全部返回 false 值时,才会调用回调。如果给出了 proc,则其主体在当前对象的上下文中进行评估。它还可以选择接受当前对象作为参数。
-
:prepend
- 如果为true
,则回调将被添加到现有链中,而不是附加到现有链之后。
# File activesupport/lib/active_support/callbacks.rb, line 776 def set_callback(name, *filter_list, &block) type, filters, options = normalize_callback_params(filter_list, block) self_chain = get_callbacks name mapped = filters.map do |filter| Callback.build(self_chain, filter, type, options) end __update_callbacks(name) do |target, chain| options[:prepend] ? chain.prepend(*mapped) : chain.append(*mapped) target.set_callbacks name, chain end end
skip_callback(name, *filter_list, &block) 链接
跳过先前设置的回调。与 set_callback
类似,可以传入 :if
或 :unless
选项,以控制何时跳过回调。
注意:此示例使用 PersonRecord
和 #saving_message
,您可以在 此处 查看其定义
class Writer < PersonRecord
attr_accessor :age
skip_callback :save, :before, :saving_message, if: -> { age > 18 }
end
当 if 选项返回 true 时,将跳过回调。
writer = Writer.new
writer.age = 20
writer.save
输出
- save
saved
当 if 选项返回 false 时,将不会跳过回调。
young_writer = Writer.new
young_writer.age = 17
young_writer.save
输出
saving...
- save
saved
如果尚未设置回调,将引发 ArgumentError
(除非 :raise
选项设置为 false
)。
来源:显示 | 在 GitHub 上
# File activesupport/lib/active_support/callbacks.rb, line 825 def skip_callback(name, *filter_list, &block) type, filters, options = normalize_callback_params(filter_list, block) options[:raise] = true unless options.key?(:raise) __update_callbacks(name) do |target, chain| filters.each do |filter| callback = chain.find { |c| c.matches?(type, filter) } if !callback && options[:raise] raise ArgumentError, "#{type.to_s.capitalize} #{name} callback #{filter.inspect} has not been defined" end if callback && (options.key?(:if) || options.key?(:unless)) new_callback = callback.merge_conditional_options(chain, if_option: options[:if], unless_option: options[:unless]) chain.insert(chain.index(callback), new_callback) end chain.delete(callback) end target.set_callbacks name, chain end end