Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is Rails before_filter called twice when the controller is subclassed?

I'm at Rails 2.3.5 and I have this problem:

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

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

The problem is that on ChildController, the :foo before filter gets called twice.

I've tried a number of workarounds around this problem. If I don't include the :index action in the child, it never gets called for that action.

The solution I found works, but I think it's very very ugly

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

Is there a better way to solve this problem?

like image 236
rubenfonseca Avatar asked May 24 '10 16:05

rubenfonseca


People also ask

What does controller do in Rails?

The Rails controller is the logical center of your application. It coordinates the interaction between the user, the views, and the model. The controller is also a home to a number of important ancillary services. It is responsible for routing external requests to internal actions.

What is around_ filter in Rails?

There are three types of filters implemented in Rails: a before_filter runs before the controller action. an after_filter runs after the controller action. an around_filter yields to the controller action wherever it chooses.

What is around filter?

Around Filters. Rails around filters contain codes that are executed both before and after controller's code is executed. They are generally used when you need both before and after filter. Its implementation is little bit different and more complex than other two filters.


2 Answers

"This behavior is by design".

The Rails guide on controllers states:

"Filters are inherited, so if you set a filter on ApplicationController, it will be run on every controller in your application."

This explains the behaviour you're seeing. It also suggests the exact same solution you propose (using skip_before_filter) to define which filters will or will not be run for a particular controller and/or methods.

So, ugly or not, seems like the solution you found is common and approved practice.

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

like image 179
Roadmaster Avatar answered Nov 15 '22 16:11

Roadmaster


If you don't want to use skip_before_filter you could always skip the index action in the ChildController:

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

But this might become a problem if you change the behavior in BaseController and remove the filter from the index action. Then it would never be called so using skip_before_filter might be a better idea.

like image 26
Tomas Markauskas Avatar answered Nov 15 '22 16:11

Tomas Markauskas