rails 是如何实现 before_filter 的? [英] How does rails implement before_filter?

查看:30
本文介绍了rails 是如何实现 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 用于将过滤器从 SymbolProc、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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆