1

可能重复:
ActiveRecord 回调和验证的顺序是什么?

我来自Java背景。我认为 Rails 中很奇怪的一件事是,您可以在类下设置回调函数,例如属性,例如before_filter.

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

我真的不明白它是如何工作的。我发现这篇文章解释了before_filter。我了解逻辑流程,这只是一种方法。但是我仍然不明白什么时候会before_filter执行设置回调链。

4

2 回答 2

14

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,它确保你用它定义的所有回调在你的普通控制器方法之前被调用。

我希望这可以为您解决一些问题。

于 2013-01-16T02:12:06.037 回答
1

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

至于它设置的回调,控制器有一个process方法,该方法采用动作的名称(例如,“索引”),并在process_action. 回调模块使用运行回调的实现覆盖此方法。

于 2013-01-16T01:33:54.503 回答