Hi,
I'd like to have a more dynamic way of working with filter chains in Ruby on Rails 2.3.2.
At the moment, the filter chain is built as the classes are loaded. I have a very particular need for the filter chain to be rebuilt at some point in time after the classes have loaded.
This is to do with a Rails project (Spree, Radiant may also be affected I'm guessing) that uses extensions which can do things like this after the filter chain has been built for MyController:
MyController.class_eval do
before_filter :my_filter_method
end
ApplicationController.class_eval do
before_filter :app_filter_method
end
The problem here is that the app_filter_method
filter will not be added to the MyController filter chain. This is because the filter chain of MyController is built from an earlier copy of the filter chain of ApplicationController. This copy of the filter chain of ApplicationController does not yet have the app_filter_method
filter applied to it.
I can think of 2 places so far that the rebuilding of the FilterChain could happen in:
1) Each time it is called on MyController.filter_chain
2) Reloadable on demand. So MyController.reload_filter_chain will rebuild the filter chain, using the filters from MyController's subclasses in the chain.
Perhaps specifying a subclass of FilterChain like ReloadableFilterChain that builds the filter chain for each request might do it - thoughts?
Here are links to the source of filters.rb on GitHub, for Ruby on Rails 2.3.2:
The filter_chain method (line 573)
The FilterChain class (line 10)
I was hoping some of you here might have some insight or advice on how to do this.
Any help much appreciated.
Eliot
More detail as requested:
Spree is a rails app that uses extensions to modify behaviour.
Sometimes an extension is used to add a filter to a controller (such as in the example code in the question). One example use is the static content extension.
The static content extension allows you to show HTML pages stored in the database to be shown for any request path you specify. For example, you could show one of these HTML pages instead of the default content Spree shows for the /products request path.
The static content extension filters all requests and checks the path. If the path matches one of the pages in the db, then the filter renders the page.
The static content extension declares its filter like so:
Spree::BaseController.class_eval do
before_filter :render_page_if_exists
def render_page_if_exists
...
end
end