14

只是我心中的一个想法。以下有什么区别

before_filter

class ApplicationController < ActionController::Base
  before_filter :foo
  def foo
    @mode = Model.new
  end
end

红宝石初始化

class ApplicationController < ActionController::Base
  def initialize
    foo
  end

  def foo
    @mode = Model.new
  end
end
  1. ruby 的初始化方法在 Rails 中是否按预期工作?
  2. 如果是,那么我们可以在适当的位置使用初始化过滤器必须应用于控制器中的所有操作吗?
4

2 回答 2

25

对于每个请求,您都会得到一个新的 实例ApplicationController,但这里最大的禁忌是您试图在ActionController::Base#initialize不调用父行为的情况下覆盖核心行为。

ApplicationController < ActionController::Base

  def initialize
    super # this calls ActionController::Base initialize
    init_foo
  end

  private

  def init_foo
    @foo = Foo.new
  end
end

这不是惯用的 Rails 行为。他们给你before_filter一个理由;所以使用它。

于 2013-09-02T15:13:51.880 回答
3

我相信Sandi Metz在Practical Object-Oriented Design in Ruby中对此进行了介绍。

假设您正在为其他开发人员/用户设计一个基类,并希望允许他们挂钩到过程中的各个步骤(例如初始化)。一般来说,有两种方法:

  1. 将过程分解为小方法,并(在文档中)提醒用户super在覆盖方法时使用。
  2. 包括对用户可以使用自定义功能覆盖的各种空钩子方法的调用。

(我相信这些是模板方法模式的变体。)

第二种方式需要您付出更多的努力,而为您的用户付出更少的努力。

在这种特定情况下,before_filter提供了一种更简洁的方式来附加多个钩子,并鼓励您将钩子分解为具有有意义名称的单一职责方法。这在使用更多控制器继承的应用程序中变得更加重要。

于 2013-09-02T17:13:44.673 回答