跳至內容 跳至搜尋

Active Model 回呼

提供介面讓任何類別具有類似 Active Record 的回呼動作。

類似 Active Record 的方式,其中一個方法擲回 :abort 時,回呼鏈就會中斷。

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

class MyModel
  extend ActiveModel::Callbacks
end

接著定義一個您希望附加回呼動作的方法清單

define_model_callbacks :create, :update

這會提供 :create:update 方法的所有三個標準回呼(在前面、中間和後面)。要實作,您需要以一個區塊包裝您希望附加回呼的方法,讓回呼有機會引發

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_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 選項,讓您可以選擇是否要所有類型(前面、中間或後面),或僅選擇一些。

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