Rails: Power to the filters
posted by gchatz 1 commentRails before_filters in controllers can help you keep your code DRY.
I have coded cases where all action functionality was included in 2-3 before_filters.
I’ll try to showcase some of the methods that work for me.
Authentication
The most commonly used before_filter should be that of authentication, and since this is global you can place it in you ApplicationController.
class ApplicationController < ActionController::Base
session :session_key => '_fortytwo_session_id'
before_filter :fetch_logged_user
def authenticate
unless @logged_user
#unauthorized access
redirect_to login_url, :status => 401
return false
end
end
def fetch_logged_user
unless session[:user_id].blank?
@logged_user = User.find(session[:user_id])
end
rescue ActiveRecord::RecordNotFound
end
end
Now, in every action, in every controller we have a @logged_user object. If it’s not nil , then we have an authenticated user.
So if we want to restrict access to authenticated users in a certain controller for some actions, we just need a before_filter for the authenticate function.
class UsersController < ApplicationController before_filter :authenticate, :except => :login endre
CRUD Operations
Models usually have the common CRUD actions (new, edit, update, delete, create), and some other actions that operate on a specific model record. If you add authentication and probably authorization (only the owner of a blog post can change his content for example), things can get complicated. Unless…
class BlogController < ApplicationController
#authenticate is in our ApplicationController
before_filter :authenticate, :except => :show
before_filter :fetch_post, :only => [:show, :edit, :update, :delete]
before_filter :authorise_as_owner, :only => [:edit, :update, :delete]
private
def fetch_post
@post = Post.find(params[:id])
rescue ActiveRecord::RecordNotFound
#there is no such post
flash[:alert] = "Got lost?"
redirect_to error_url, :status => 404
return false
end
def authorise_as_owner
unless @post.user_id == @logged_user.id
#You don't belong here. Go away.
flash[:alert] = "Mind your own business"
redirect_to error_url, :status => 401
end
end
end
If you are using roles, you can extend the authorisation behaviour (so that admins can edit any post) like this:
def authorise
unless @post.user_id == @logged_user.id || @logged_user.is_admin?
#You don't belong here. Go away.
flash[:alert] = "Mind your own business"
redirect_to error_url, :status => 401
end
end

Comments (1)
Hi, the code above is not coming up as syntax highlighted.