Snippet: using 'inherited' to set filters in controllers
Posted by trevor Fri, 26 May 2006 22:51:37 GMT
One of my apps has a set of controllers in an ’/admin’ directory. They all must have a :login_required
before_filter and they all must define an authorized?
method that checks if the current user is an administrator.
For a couple of reasons the idea of having a special “AdminController” which everything under ’/admin’ would inherit from (and that set up the filter and authorized? method) kind of irked me.
First, there was the name clash – AdminController becomes ‘admin’ in routes and that clashes with my directory called ‘admin’, so I’d have to choose a name like “AdminBaseController” or some-such. Blech.
Second, I just didn’t like the extra file for the base controller. Call me picky, I can take it.
What I wanted was a way to say “if the controller is in the /admin directory then it needs this filter and this method”.
Class#inherited to the rescue. Here’s what I put in /app/controllers/application.rb
:
# For all controllers in the 'Admin' namespace we set
# the login_required before_filter and define an authorized?
# method that checks user.is_administrator?
def self.inherited(subclass)
# call super first - otherwise any before_filters we add are lost
super
if subclass.name.split('::').first == 'Admin'
subclass.before_filter :login_required
subclass.send(:define_method, :authorized?, Proc.new {|user| user.is_administrator?})
subclass.send(:protected, :authorized?)
end
end
This is fine for my present needs. If controllers under /admin start to need any more shared behavior I’ll just bite the bullet and do the AdminBaseController thing – but for now this is clean and works.