1

The code below shows two controllers that have before_filters added in different orders. As a result, the controllers have different behavior.

When current_user is nil (logged out):

  • FooController -> redirects to login_path
  • BarController -> redirects to root_path

You could, of course, combine the two methods and make them smarter to make this specific example go away -- but that is missing the point of this question.

The issue at hand is that, in ActionController, the order that filters get added is relevant. (You could also argue that that implementation isn't the greatest, but that's how it is -- so let's move on)

Since that's how ActionController works, I would like to test that behavior. However, it isn't necessary to test the results of the before filters on each individual action (not DRY). As far as I can figure, what's actually important is the resulting order of the filter chain on each action.

The only thing that before_filter :require_user actually does is inject an item into the callback chain - and that's all I should have to test for in my subclasses - that an additional item has been added to the chain. I don't need to test the effect that require_user has on my actions - they can, and should, be stubbed.

That all said, here's the money question: Is there a public API that returns what methods are in a given controller and action's filter chain? This should include before, after and around filters in their appropriate order.

class ApplicationController < ActionController::Base
  def require_user
    unless current_user
      redirect_to login_path and return
    end
  end
  def require_admin
    unless current_user.try(:admin?)
      redirect_to root_path and return
    end
  end
end

class FooController < ApplicationController
  before_filter :require_user
  before_filter :require_admin
end

class BarController < ApplicationController

  # reverse the order of the filters

  before_filter :require_admin
  before_filter :require_user
end
jsharpe
  • 2,546
  • 3
  • 26
  • 42

1 Answers1

0

You can access the list of filters via the _process_action_callbacks class method. For a list of filters, you can:

FooController._process_action_callbacks.collect &:filter
ReggieB
  • 8,100
  • 3
  • 38
  • 46
  • I was poking around in there.... it's the wild west. It might be a public method, but I don't get the sense that it's meant to be used as an API. Not only that, but map(&:filter) doesn't account for the order of before/around filters. – jsharpe Apr 29 '14 at 21:44