rails 是如何实现 before_filter 的? [英] How does rails implement before_filter?
问题描述
我对 rails 如何实现像 before_filter
这样的过滤器很感兴趣.
I'm interested in how rails implement filters like before_filter
.
但是看了源码,还是一头雾水.
But after reading the source code, I'm still confused.
我注意到rails的框架维护了一个filter_chain
,并且在目标方法之前运行过滤器.
I noticed that rails' framework maintains a filter_chain
, and run the filters before the target method.
但是,我不明白一个重要的过程:rails 如何捕获方法调用?
But, I do not understand an important process: how does rails capture a method calling?
我的意思是,例如,我有一个 Dog
类,并为方法 bark 设置了一个 before_filter
.
I mean, for example, I have a class Dog
, and set a before_filter
to the method bark.
当我调用 dog.bark
时,rails 应该以某种方式捕获这个调用,并运行其修改后的方法.
When I call dog.bark
, rails should capture this calling in some way, and run its modified method instead.
但是,我在源代码中没有找到这样的代码.
However, I do not find such code in the source code.
谁能告诉我这个想法或指出代码在哪里?
Can anyone tell me the idea or point out where the code lies?
推荐答案
当您设置 before_filter
或任何类似的过滤器 (想想 after_filter
, around_filter
),您可以使用 符号 或 Proc、lambda或阻止.
When you set a before_filter
, or any similar filter (think after_filter
, around_filter
), you're doing so with either a Symbol or a Proc, lambda or block.
before_filter :bark
before_filter Proc.new { |k| k.bark }
以上将符号或块附加到堆栈中 此处,通过调用<代码>set_callback.这将构建您所指的链".
The above appends the symbols or blocks to a stack here, by calling set_callback
. This builds the 'chain' you're referring to.
这个链"中的每一项都是 ActiveSupport::Callbacks::Callback
类.这个班知道
Each item in this 'chain' is an instance of the ActiveSupport::Callbacks::Callback
class. This class knows
- 它必须运行的方法(符号)或块(即你的类的
:bark
方法) - 它必须在中运行的上下文(即你的
Dog
类)
Callback
实例附加到 ActiveSupport::Callbacks::CallbackChain
在 __update_callbacks
.
The Callback
instances are appended to a ActiveSupport::Callbacks::CallbackChain
in __update_callbacks
.
当每个 Callback
类被初始化时,_compile_filter
用于将过滤器从 Symbol
、Proc
、lambda 或块标准化为一个常见的可调用格式.
When each Callback
class is initialized, _compile_filter
is run to normalize the filter from the Symbol
, Proc
, lambda, or block into a common, callable format.
最后,当 CallbackChain
运行时,它会调用 start
在每个 Callback
实例上,以及 此时strong> 过滤器实际上是在适当的上下文中执行的.
Finally, when the CallbackChain
is run, it will call start
on each Callback
instance, and its at this point that the filter is actually executed within the proper context.
重要的是要指出您不会创建像
It's important to point out that you would not create a filter like
before_filter dog.bark
这将执行 dog.bark
并将其返回值传递给 before_filter
以附加到 CallbackChain
.目的是将某种指令传递给 before_filter
以便 Rails 稍后为您执行.你会做类似的事情
this is going to execute dog.bark
and pass it's return value to before_filter
to be appended to the CallbackChain
. The intention is to pass some sort of instruction on to before_filter
for Rails to later execute for you. You would instead do something like
before_filter Proc.new { d = Dog.new; d.bark }
Proc
中的代码没有被执行.当上面的行由 Rails 运行时.相反,Rails 被告知将 Proc
传递给 CallbackChain
.Proc
是您传递给 Rails 以在适当的时间执行的指令".
The code within the Proc
is not executed. when the line above is run by Rails. Instead, Rails is being told to pass the Proc
to the CallbackChain
. The Proc
is the 'instruction' you're passing on to Rails to execute at the appropriate time.
rails 怎么知道我调用了 :bark
how in the first place does rails know I have called :bark
至于这个,假设你的 Dog
类被简单地定义为
As for this, let's say your Dog
class is simply defined as
class Dog
def bark
end
def eat
end
end
(虽然这是一个糟糕的例子),你可能想要像
before_bark :eat
这需要您定义bark
回调,然后告诉您的bark
方法运行相关的bark
回调.
This requires you define the bark
callback, and then tell your bark
method to run the related bark
callbacks.
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::回调
就是这样做的.
You can see how ActiveRecord::Callbacks
does this.
尽管这确实是一个糟糕的例子,因为您可以(并且应该)直接从 bark
调用 eat
,但这应该能说明问题.
This really is a bad example though because you can (and should) just call eat
directly from bark
, but this should get the point across.
这篇关于rails 是如何实现 before_filter 的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!