Using Rails’ before_filter is a great way to keep your controller actions clean by moving logic about authentication, authorization, or state of the resource out of the main method, right?
Here’s a typical usage of before_filter:
class Admin::ArticlesController < ApplicationController
before_filter :deny_access, :unless => :draft_and_admin?
def show
@article = Article.find(params[:id])
end
protected
def draft_and_admin?
Article.find(params[:id]).draft? && current_user.admin?
end
end
Awesome. We deny the user access to the show action if the article is a draft and they are not an admin. The show action looks “standard”. When we look at the top of the file, we see a nice one-liner encapsulating concerns of authorization.
If we were using a RESTful controller abstraction such as inherited_resources, our code might look like this:
class Admin::ArticlesController < InheritedResources::Base
before_filter :deny_access, :unless => :draft_and_admin?
actions :show
protected
def draft_and_admin?
Article.find(params[:id]).draft? && current_user.admin?
end
end
The shortest of our three options, this approach requires more knowledge of the libraries in use.
What if it looked like this?
class Admin::ArticlesController < ApplicationController
def show
if draft_and_admin?
@article = Article.find(params[:id])
render
else
deny_access
end
end
protected
def draft_and_admin?
Article.find(params[:id]).draft? && current_user.admin?
end
end
This is not standard Rails!
Yet all the logic is inline inside the action. It reads sequentially. It even has an explicit render in there, thumbing its nose at the Rails way!
The core responsibility of the action (fetching the Article of a given id) is more muddled here but the path of the code is clear to any Rubyist. No special knowledge required.
What advantage does before_filter provide that Ruby does not? Does the before_filter layer of indirection make the code easier or harder to read? Do RESTful controller abstractions influence our preference?