Friday, August 14, 2009

Inherit Filters, Don't Inundate Your Controllers With Them

Filters are a great way to keep your controllers DRY, but to fully optimize their use a developer should take advantage of controller inheritance (filters are inherited as well as the actions).

I happen to be a big believer in nested controllers. We tend to use the small controller, large model approach in our Rails structure. This philosophy naturally results in numerous controllers. I also think a nested structure is especially relevant in a site that has many Ajax functions sprinkled throughout every page.

Since nested controllers tend to represent a subset of functionality provided by the higher level controller, it makes sense to inherit from this controller (Note: ALL controllers by default inherit from the application controller. When creating a nested controller, the namespace will reflect the parent, but you must manually change the controller from which it inherits).

It's common practice to implement filters on the Application controller that apply to the entire site (ie an authentication filter). However, specialized filters such as functionality specific permissions or state checking should not be applied to the Application controller. Otherwise, you will end up with skip_before_filters all over the place. This is poor practice.
So here's a simple example of a good way to use nested controllers in conjunction with filters:

class ClientController < ApplicationController

before_filter :verify_client_permission

def view_client_information
//some code
end

end

class Client::EditClientController < ClientController
//inherits filter from ClientController
end

Of course this is an extremely simple example, but I think it gets the point across. As with everything in Rails, there are probably numerous ways to accomplish the same idea. This is the method I have found that works well in pretty large Rails projects with a complex permissions model and lots of Ajax.

No comments:

Post a Comment