当您设置 abefore_filter
或任何类似的过滤器(想想after_filter
, around_filter
)时,您可以使用Symbol或Proc、 lambda 或块。
before_filter :bark
before_filter Proc.new { |k| k.bark }
上面通过调用将符号或块附加到此处set_callback
的堆栈中。这构建了您所指的“链”。
此“链”中的每个项目都是该类的一个实例ActiveSupport::Callbacks::Callback
。这个班知道
- 它必须运行的方法(符号)或块(即您的类的
:bark
方法)
- 它必须在其中运行的上下文(即您的
Dog
班级)
Callback
实例附加到ActiveSupport::Callbacks::CallbackChain
in 。__update_callbacks
当每个Callback
类初始化时,_compile_filter
运行以将过滤器从Symbol
、Proc
、 lambda 或块标准化为通用的可调用格式。
最后,当CallbackChain
运行时,它将调用start
每个Callback
实例,此时过滤器实际上是在适当的上下文中执行的。
重要的是要指出您不会创建像这样的过滤器
before_filter dog.bark
这将执行dog.bark
并将其返回值传递before_filter
给附加到CallbackChain
. 目的是将某种指令传递before_filter
给 Rails 以便稍后为您执行。你会改为做类似的事情
before_filter Proc.new { d = Dog.new; d.bark }
中的代码Proc
未执行。当上面的行由 Rails 运行时。相反,Rails 被告知Proc
将CallbackChain
. 这Proc
是您传递给 Rails 以在适当的时间执行的“指令”。
首先,rails 是如何知道我打过电话的:bark
至于这个,假设你的Dog
类被简单地定义为
class Dog
def bark
end
def eat
end
end
(虽然这是一个可怕的例子),你可能想要有类似的东西
before_bark :eat
这需要您定义bark
回调,然后告诉您的bark
方法运行相关的bark
回调。
class Dog
extend ActiveModel::Callbacks
define_callbacks :bark
before_bark :eat
def bark
run_callbacks(:bark) { YOUR BARK CODE HERE }
end
def eat
end
end
你可以看看这是怎么ActiveRecord::Callbacks
做到的。
这确实是一个不好的例子,因为您可以(并且应该)eat
直接从 调用bark
,但这应该明白这一点。