跳到內容 跳到搜尋

Active Model 回呼

提供介面讓任何類別都能有類似 Active Record 的回呼。

與 Active Record 方法相同,只要其中一個方法傳回 :abort,回呼鏈就會中斷。

首先,從您正在建立的類別延伸 ActiveModel::Callbacks

class MyModel
  extend ActiveModel::Callbacks
end

然後定義您想要附加回呼的清單

define_model_callbacks :create, :update

這將為 :create:update 方法提供所有三種標準回呼(before、around 和 after)。要實作,您需要將您想要附加回呼的方法包在一個區塊中,讓回呼有機會觸發

def create
  run_callbacks :create do
    # Your create action methods here
  end
end

然後在您的類別中,您可以使用 before_createafter_createaround_create 方法,就像在 Active Record 模型中一樣。

before_create :action_before_create

def action_before_create
  # Your code here
end

在定義 around 回呼時,請記得傳遞區塊,否則它不會被執行

around_create :log_status

def log_status
  puts 'going to call the block...'
  yield
  puts 'block successfully called.'
end

您可以選擇僅透過傳遞雜湊給 define_model_callbacks 方法來取得特定回呼。

define_model_callbacks :create, only: [:after, :before]

只會在您的類別中建立 after_createbefore_create 回呼方法。

注意:多次呼叫同一個回呼會覆寫先前的回呼定義。

方法
D
包含的模組

實例公開方法

define_model_callbacks(*callbacks)

define_model_callbacks 接受與 define_callbacks 相同的選項,以防您想要覆寫預設值。除此之外,它也接受一個 :only 選項,讓您可以選擇是否要所有類型(before、around 或 after),或僅選擇部分類型。

define_model_callbacks :initialize, only: :after

請注意,only: <type> 雜湊會套用在該方法呼叫中定義的所有回呼。要解決這個問題,您可以根據需要多次呼叫 define_model_callbacks 方法。

define_model_callbacks :create,  only: :after
define_model_callbacks :update,  only: :before
define_model_callbacks :destroy, only: :around

只會建立 after_createbefore_updatearound_destroy 方法。

您可以傳遞一個類別給 before_<type>、after_<type> 和 around_<type>,在這種情況下,回呼會呼叫該類別的 <action>_<type> 方法,傳遞回呼正在呼叫的物件。

class MyModel
  extend ActiveModel::Callbacks
  define_model_callbacks :create

  before_create AnotherClass
end

class AnotherClass
  def self.before_create( obj )
    # obj is the MyModel instance that the callback is being called on
  end
end

注意:傳遞給 define_model_callbacksmethod_name 不能以 !?= 結尾。

# File activemodel/lib/active_model/callbacks.rb, line 109
def define_model_callbacks(*callbacks)
  options = callbacks.extract_options!
  options = {
    skip_after_callbacks_if_terminated: true,
    scope: [:kind, :name],
    only: [:before, :around, :after]
  }.merge!(options)

  types = Array(options.delete(:only))

  callbacks.each do |callback|
    define_callbacks(callback, options)

    types.each do |type|
      send("_define_#{type}_model_callback", self, callback)
    end
  end
end