Controller Inheritance 7
Just a brief interlude from the File Management series while I sort out some time to do some benchmarking.
A common pattern I see in submissions and client-applications is repetitive declarations in controllers. There’s a neat and simple solution for this, but given how often Things like this:
class TodoController < ApplicationController
before_filter :login_required
before_filter :handle_iphone_support
before_filter :fetch_todo
around_filter :performance_logging
def index
...
end
end
For a single controller this set of declarations wouldn’t be a problem, but the problem is when all those declarations end up duplicated in several different controllers. Thankfully every controller inherits from ApplicationController so we can do something like this:
class ApplicationController < ActionController::Base
before_filter :login_required
before_filter :handle_iphone_support
around_filter :performance_logging
end
class TodoController < ApplicationController
before_filter :fetch_todo
def index
...
end
end
This is easy, and obvious and most people do that. However what do you do when you have several controllers which don’t need the login_required call? One option is to give up on inheritance and go back to copying-and-pasting the filter declarations. Another option is to selectively opt-out of the parent controller’s filters.
class ApplicationController < ActionController::Base
before_filter :login_required
before_filter :handle_iphone_support
around_filter :performance_logging
end
class SignupController < ApplicationController
skip_before_filter :login_required
end
However if you have several controllers which don’t require logins, you’ll find yourself duplicating the skip_before_filter declarations around. Otherwise filters and declarations which aren’t completely universal still. An approach which solves this nicely is to introduce an abstract parent controller for all your authenticated controllers.
class ApplicationController < ActionController::Base
before_filter :handle_iphone_support
around_filter :performance_logging
end
class AuthenticatedController < ApplicationController
before_filter :login_required
end
class TodoController < AuthenticatedController
before_filter :fetch_todo
def index
...
end
end
This technique doesn’t just work with filter declarations most other declarations such as caching, session and csrf options work as expected too. In addition you can introduce several parent classes as needed such as a PublicController with page caching declarations, an AdminController for your admin panels etc. Inheritance isn’t the solution to every case of duplicate declarations, yet it’s a simple technique that can simplify most uses.

The Rails Way is all about teaching "best practices"
in 