Ruby on Rails before_filter vs ruby ​​initialize

Просто мысль в моем сознании. в чем разница:

before_filter

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

ruby ​​initialize

class ApplicationController < ActionController::Base
  def initialize
    foo
  end

  def foo
    @mode = Model.new
  end
end
  • Используется ли метод инициализации ruby, как и ожидалось в рельсах?
  • Если да, то можно ли использовать инициализацию на месте, фильтр должен применяться ко всем действиям в контроллере?

Ответ 1

Для каждого запроса вы получаете новый экземпляр 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 по какой-то причине; поэтому используйте его.

Ответ 2

Я считаю, что это было рассмотрено в Практическом объектно-ориентированном дизайне в Ruby от Sandi Metz.

Предположим, вы разрабатываете базовый класс для других разработчиков/пользователей и хотите разрешить им подключаться к различным этапам процедуры (например, инициализации.) В общем, существует два способа:

  • Разбейте процедуру на небольшие методы и (в документации) напомните пользователям использовать super всякий раз, когда они переопределяют метод.
  • Включает вызовы различных методов пустых меток, которые пользователи могут переопределять с помощью специальных функций.

(Я считаю, что это вариации шаблона Template Method.)

Второй способ требует больше усилий с вашей стороны и меньше усилий для ваших пользователей.

В этом конкретном случае before_filter предоставляет более чистый способ подключения нескольких крючков и призывает вас разбить крючки на методы с одной ответственностью со значимыми именами. Это становится более важным в приложениях, которые используют больше наследования контроллера.