rails如何实现before_filter?
我对rails如何实现像before_filter
这样的filter感兴趣。
但在阅读完源代码后,我仍然感到困惑。
我注意到rails的框架维护了filter_chain
,并在目标方法之前运行filter。
但是,我不明白一个重要的过程:rails如何捕获一个方法调用?
我的意思是,例如,我有一个类Dog
,并为方法树皮设置了before_filter
。
当我调用dog.bark
,rails应该以某种方式捕获此调用,并改为运行其修改后的方法。
但是,我在源代码中找不到这样的代码。
任何人都可以告诉我这个想法或指出代码所在的位置吗?
当您设置before_filter
或任何类似的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
。
初始化每个Callback
类时,运行_compile_filter
以将filter从Symbol
, Proc
,lambda或块规范化为通用的可调用格式。
最后,当运行CallbackChain
时,它将在每个Callback
实例上调用start
, 此时它将在适当的上下文中实际执行filter。
重要的是要指出你不会创建像这样的filter
before_filter dog.bark
这将执行dog.bark
并将其返回值传递给before_filter
以附加到CallbackChain
。 目的是将一些指令传递给before_filter
for Rails以便稍后执行。 你会做类似的事情
before_filter Proc.new { d = Dog.new; d.bark }
Proc
的代码未执行。 当上面的行由Rails运行时。 相反,Rails被告知将Proc
传递给CallbackChain
。 Proc
是您传递给Rails以在适当时间执行的“指令”。
铁轨知道我怎么称呼:树皮
至于这个,让我们说你的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
如何做到这一点。
这真的是一个不好的例子,因为你可以(而且应该)直接从bark
直接打电话eat
,但这应该得到重点。
Rails不会按照您描述的方式捕获方法调用。 如果查看AbstractController::Base.process
,它将查找要为调度操作调用的方法,运行filter然后调用实际方法。 换句话说,您的控制器方法不是直接调用,而是通过此process
方法调用。
- 鞋子和gem
- 安装rubyracer时出错,错误“gem gem:package is corrupt”
- 如何通过jquery / ajax作为JSON对象将数据发送和存储到rails?
- 使用FasterCSV gem解决CSV解析的基本问题
- 由于缺少libmysql,在Windows上安装mysql-2.9.0 gem失败
- rails helper方法如何:attribute_changed? 在Rails 3.2.15中有效吗?
- 使用Postgresql在Datamapper中像(ilike)一样不区分大小写
- 学习Ruby:推荐博客阅读?
- RubyInstaller 2.2.1和Rails – Rake无法加载Nokogiri