什么时候执行了before_filter?

时间:2013-01-16 01:13:01

标签: ruby-on-rails

  

可能重复:
  What is the order of ActiveRecord callbacks and validations?

我来自Java的背景。我认为在Rails中非常怪异的一件事是你可以在类的下面设置回调函数,例如before_filter

class SomeController < ActionController::Base
  before_filter Proc.new {.....}
end

我真的不明白它是如何运作的。我找到了解释before_filter的{​​{3}}。我理解逻辑的流程,它只是一种方法。但我仍然不明白何时执行before_filter来建立回调链。

2 个答案:

答案 0 :(得分:12)

before_filter不是Ruby特性,它是由 Ruby on Rails (Web框架)提供的类方法,您可以在控制器中使用它来执行一段代码之前执行控制器中的任何操作。

那么,Ruby on Rails是如何做到的呢?

当你在Ruby中定义一个类时,你实际上是在执行代码,在irb中尝试这个:

class Hello
  puts "defining hello..."

  def greet
    puts "Hello there"
  end
end

当你定义类时,你会看到“定义你好......”会在终端中打印出来。您还没有实例化任何对象,您只是定义了一个类,但您可以在定义类的过程中执行任何代码。

你知道你可以定义“类方法”和“实例方法”,有趣的是你可以在定义类时调用类方法:

class MyClass
  def self.add_component(component)
    # Here @@components is a class variable
    @@components ||= []        # set the variable to an empty array if not already set.
    @@components << component  # add the component to the array
  end

  add_component(:mouse)
  add_component(:keyboard)
  add_component(:screen)

  def components
    @@components # The @@ gets you the class variable
  end
end

MyClass.new.components
=> [:mouse, :keyboard, :screen]

def self.add_component定义了一个可以在定义类时调用的类方法。在此示例中,add_component将键盘添加到类变量中的列表中,def components实例方法(在此类的实例上调用)访问此类变量。类方法可以在父类中定义,它也可以使用相同的方法。这个例子可能有点奇怪。

我们再做一个例子。

class RubyOnSlugsController
  def self.before_filter(callback)
    @@callbacks ||= []
    @@callbacks << callback
  end

  def execute_callbacks
    @@callbacks.each { |callback| callback.call() }
    return "callbacks executed"
  end
end

class MyController < RubyOnSlugsController
  before_filter Proc.new { puts "I'm a before filter!" }
  before_filter Proc.new { puts "2 + 2 is #{2 + 2}" }
end

controller = MyController.new
controller.execute_callbacks

将输出:

I'm a before filter!
2 + 2 is 4
=> "callbacks executed"

Ruby on Rails使用before_filter执行类似(但更复杂)的操作,并确保在您使用普通控制器方法之前调用您使用它定义的所有回调。

我希望这能为你解决一些问题。

答案 1 :(得分:1)

加载控制器文件时(即服务器启动时),before_filter方法本身会运行。这意味着一旦定义了类就建立了回调链。

对于它设置的回调,控制器有一个process方法,它采用一个动作的名称(比如“index”),并在process_action中调用相应的动作方法。回调模块使用runs the callback

的实现覆盖此方法