# Bug in Rails 1.1 implementation of before\_filters

**URL:** <https://www.ruby-forum.com/t/bug-in-rails-1-1-implementation-of-before-filters/58719>\
**Category:** Rails\
**Created:** [April 25, 2006, 9:13am UTC](https://www.ruby-forum.com/t/bug-in-rails-1-1-implementation-of-before-filters/58719 "2006-04-25T09:13:02Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![grahamglass](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/839c29/32.png) [@grahamglass](https://www.ruby-forum.com/u/grahamglass)\
**Post date:** [April 25, 2006, 9:13am UTC](https://www.ruby-forum.com/t/bug-in-rails-1-1-implementation-of-before-filters/58719/1 "2006-04-25T09:13:02Z")

</div>

I just spent a few hours tracking down a bug in Rails 1.1, so I thought  
I’d post the issue and a workaround just in case anyone else hits it.

I designed a security enhancement so that controller methods can be  
protected by preceding them with a role. The standard Ruby  
method\_added() callback is used to detect when controller methods are  
added, and then I manipulate the controller’s before\_filter chain  
appropriately. My code worked fine in Rails 1.0, and then stopped  
working in Rails 1.1.

I eventually tracked down the bug to the new implementation of  
ActionController::Filters::before\_filters and include\_actions, which  
cache their results the first time they are called. This caching  
approach works fine as long as before\_filters and include\_actions are  
only called _after_ all the filters have been registered, but I was  
using them _during_ the registration process to figure out how to  
manipulate the filter chain. Since Rails 1.1 caches their value the  
first time they’re called, their return value is out of date if more  
filters are added.

A workaround is to bypass the cache and use  
read\_inheritable\_attribute(“before\_filters”) instead of before\_filters.  
Similarly, use read\_inheritable\_attribute(“included\_actions”) instead of  
included\_actions. This is bad because now my code is tied to an  
implementation detail which would normally be hidden.

Incidentally, the same bug also occurs in after\_filters and  
excluded\_actions.

Cheers,  
Graham

---

<div class="post-metadata">

**Author:** ![grahamglass](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/839c29/32.png) [@grahamglass](https://www.ruby-forum.com/u/grahamglass)\
**Post date:** [April 25, 2006, 11:19pm UTC](https://www.ruby-forum.com/t/bug-in-rails-1-1-implementation-of-before-filters/58719/2 "2006-04-25T23:19:58Z")

</div>

Stefan K. wrote:

> Graham G. wrote:
> 
> > I eventually tracked down the bug to the new implementation of  
> > read\_inheritable\_attribute(“before\_filters”) instead of before\_filters.  
> > Similarly, use read\_inheritable\_attribute(“included\_actions”) instead of  
> > included\_actions. This is bad because now my code is tied to an  
> > implementation detail which would normally be hidden.
> 
> Incidentally, your previous code relied on an implementation detail as  
> well: namely, that the values returned by “before\_filters” and  
> “included\_actions” were recomputed on each call.
> 
> The named methods are usually only called during request processing. In  
> fact, they are pretty much internal to the filter implementation.  
> Caching the return values improved performance, sometimes significantly,  
> so it was decided to cache them.
> 
> If you really need to modify the filter chain in your app, use  
> read\_inheritable\_attribute(“before\_filters”), or define your own version  
> of “before\_filters” etc, or simply overwrite the methods with their old  
> version, by requiring the following code from your environment.rb file:
> 
> class ActionController::Base
> 
> class \<\< self  
> # Returns all the before filters for this class and all its  
> ancestors.  
> def before\_filters #:nodoc:  
> read\_inheritable\_attribute(‘before\_filters’) || []  
> end
> 
> ```
> # Returns all the after filters for this class and all its 
> 
> ```
> 
> ancestors.  
> def after\_filters #:nodoc:  
> read\_inheritable\_attribute(‘after\_filters’) || []  
> end
> 
> ```
> # Returns a mapping between filters and the actions that may run 
> 
> ```
> 
> them.  
> def included\_actions #:nodoc:  
> read\_inheritable\_attribute(‘included\_actions’) || {}  
> end
> 
> ```
> # Returns a mapping between filters and actions that may not run 
> 
> ```
> 
> them.  
> def excluded\_actions #:nodoc:  
> read\_inheritable\_attribute(‘excluded\_actions’) || {}  
> end  
> end  
> end
> 
> > Incidentally, the same bug also occurs in after\_filters and excluded\_actions.
> 
> It’s a feature, not a bug.
> 
> – stefan
> 
> –  
> For rails performance tuning, see: [RailsExpress.blog](http://railsexpress.de/blog)  
> Subscription: [railsexpress.de](http://railsexpress.de/blog/xml/rss20/feed.xml)

Hi Stefan,

I think it would be good if there were public apis with well-defined  
semantics that allowed runtime access to the filter chain. The  
approaches that you recommend are not guaranteed to work on future  
versions of Rails.

Right now, “before\_filters” does not do what its documentation says it  
does, so I consider this to be a bug, not a feature.

Cheers,  
Graham

---

<div class="post-metadata">

**Author:** ![grahamglass](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/839c29/32.png) [@grahamglass](https://www.ruby-forum.com/u/grahamglass)\
**Post date:** [April 25, 2006, 1:56pm UTC](https://www.ruby-forum.com/t/bug-in-rails-1-1-implementation-of-before-filters/58719/3 "2006-04-25T13:56:39Z")

</div>

Graham G. wrote:

> I eventually tracked down the bug to the new implementation of  
> read\_inheritable\_attribute(“before\_filters”) instead of before\_filters.  
> Similarly, use read\_inheritable\_attribute(“included\_actions”) instead of  
> included\_actions. This is bad because now my code is tied to an  
> implementation detail which would normally be hidden.

Incidentally, your previous code relied on an implementation detail as  
well: namely, that the values returned by “before\_filters” and  
“included\_actions” were recomputed on each call.

The named methods are usually only called during request processing. In  
fact, they are pretty much internal to the filter implementation.  
Caching the return values improved performance, sometimes significantly,  
so it was decided to cache them.

If you really need to modify the filter chain in your app, use  
read\_inheritable\_attribute(“before\_filters”), or define your own version  
of “before\_filters” etc, or simply overwrite the methods with their old  
version, by requiring the following code from your environment.rb file:

class ActionController::Base

class \<\< self  
# Returns all the before filters for this class and all its  
ancestors.  
def before\_filters #:nodoc:  
read\_inheritable\_attribute(‘before\_filters’) || []  
end

```
# Returns all the after filters for this class and all its 

```

ancestors.  
def after\_filters #:nodoc:  
read\_inheritable\_attribute(‘after\_filters’) || []  
end

```
# Returns a mapping between filters and the actions that may run 

```

them.  
def included\_actions #:nodoc:  
read\_inheritable\_attribute(‘included\_actions’) || {}  
end

```
# Returns a mapping between filters and actions that may not run 

```

them.  
def excluded\_actions #:nodoc:  
read\_inheritable\_attribute(‘excluded\_actions’) || {}  
end  
end  
end

> Incidentally, the same bug also occurs in after\_filters and excluded\_actions.

It’s a feature, not a bug.

– stefan

–  
For rails performance tuning, see: [RailsExpress.blog](http://railsexpress.de/blog)  
Subscription: [railsexpress.de](http://railsexpress.de/blog/xml/rss20/feed.xml)
