跳至内容 跳至搜索

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 回调时,请记住要 yield 到块中,否则它将不会执行

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