實例公開方法
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
- 決定 after 回呼是否應由:terminator
選項終止。預設上,無論回呼鏈是否終止,都會執行 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」為「save」。在此脈絡中,: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) 連結
移除給定事件的所有已設定回呼。
來源:顯示 | 在 GitHub 上
# 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
回呼可以指定為命名實例方法的符號;作為程序、lambda 或區塊;或作為回應由 define_callbacks
的 :scope
參數決定的特定方法的物件。
如果給定程序、lambda 或區塊,其主體會在目前物件的脈絡中評估。它也可以選擇接受目前物件作為參數。
Before 和 around 回呼會按照設定順序呼叫;after 回呼會按照相反順序呼叫。
如果事件沒有中斷,around 回呼可以從 yield
呼叫存取其回傳值。
選項
-
:if
- 符號或符號陣列,每個符號都命名實例方法或程序;只有當它們全部回傳 true 值時,才會呼叫回呼。如果給定程序,其主體會在目前物件的脈絡中評估。它也可以選擇接受目前物件作為參數。
-
:unless
- 一個符號或符號陣列,每個符號命名一個實例方法或一個程序;只有當它們全部傳回 false 值時,才會呼叫回呼。如果給定程序,其主體會在目前物件的脈絡中評估。它也可以選擇接受目前物件作為參數。
-
:prepend
- 如果為true
,會將回呼加到現有鏈之前,而不是加到後面。
來源:顯示 | 在 GitHub 上
# 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
如果尚未設定回呼(除非 :raise
選項設定為 false
),將會引發 ArgumentError
。
來源:顯示 | 在 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