Почему Rails before_filter вызывается дважды, когда контроллер подклассифицирован?

Я на Rails 2.3.5, и у меня есть эта проблема:

class BaseController < ApplicationController
  before_filter :foo, :only => [:index]
end

class ChildController < BaseController
  before_filter :foo, :only => [:index, :show, :other, :actions]
end

Проблема заключается в том, что в ChildController: foo перед тем, как фильтр дважды вызывается.

Я пробовал несколько обходных решений этой проблемы. Если я не включаю действие :index в дочерний элемент, он никогда не будет вызван для этого действия.

Решение, которое я нашел, работает, но я считаю это очень уродливым

skip_before_filter :foo
before_filter :foo, :only => [:index, :show, :other, :actions]

Есть ли лучший способ решить эту проблему?

Ответы

Ответ 1

"Это поведение по дизайну".

В руководстве Rails на контроллерах указано:

"Фильтры наследуются, поэтому, если вы установите фильтр на ApplicationController, он будет запущен на каждом контроллере в вашем приложении."

Это объясняет поведение, которое вы видите. Он также предлагает то же самое решение, которое вы предлагаете (используя skip_before_filter), чтобы определить, какие фильтры будут или не будут выполняться для конкретного контроллера и/или методов.

Итак, уродливый или нет, похоже, что решение, которое вы нашли, является распространенной и утвержденной практикой.

http://guides.rubyonrails.org/action_controller_overview.html#filters

Ответ 2

Если вы не хотите использовать skip_before_filter, вы всегда можете пропустить действие index в ChildController:

class ChildController < BaseController
  before_filter :foo, :only => [:show, :other, :actions]
end

Но это может стать проблемой, если вы измените поведение в BaseController и удалите фильтр из действия index. Тогда это никогда не будет вызвано, поэтому использование skip_before_filter может быть лучшей идеей.