Handling user roles in Rails
Here’s a nice way to deal with user roles.
1 2 3 4 5 6 7 8 9 10 | # application.rb def require_role(role, options = {}) before_filter(options) do logged_in? && current_user.send("#{role.to_s}?") ? true : access_denied end end # any controller require_role :admin, :only => [:destroy] require_role :author, :only => [:show, :edit, :create] |
Of course, there’d need to be admin? and author? methods on the user object. This could be handled in a number of ways, two of which are:
1 2 3 4 5 6 7 8 9 10 11 | # user.rb # 1) dynamically define each role using define_method %w{admin author guest}.each do |role| define_method("#{role}?") { self.role == role } unless method_defined? "#{role}?" end # 2) use method_missing to catch the undefined method def method_missing(method) self.role == method.to_s.gsub(/?/, '') end |
This code is untested and was realized by something I read this evening—just wanted to make note of it…

Chris Monday, 08 Oct, 2007 Posted at 06:39AM
In slate, I created a Permissions module that does role-based authentication in a similar fashion. The permission system is based on a set of predefined roles: writer, publisher, and administrator. Here’s the basic idea:
Note that the three roles “build” on each other, such that adminstrator will have access to all actions that require the publisher role automatically.
When the
permissionsmethod is called, a before filter is created that ensures the current user has the proper role. If that fails, a permission denied error is rendered. The module also defineshas_permission?to perform checks for permission to other controller/action pairs from within a controller or view.Ryan Monday, 08 Oct, 2007 Posted at 12:11PM
Sweet… sounds pretty organized. I’m curious what the
permissionsimplementation looks like. I imagine each of theadministratorandpublishermethods are what turn into before filters?Well I guess you’re probably merging the check somehow to consider publisher and admin in the same filter? Anyway… just curious.
This legacy .NET system we have lingering around has about 10 roles or so (that build upon one another), and a few of them pass off to another system entirely. It’s ugly and horrible to work with. Roles are always a pain, especially when (like you mentioned) they build off of each other, which is typical a lot of the time.
Admittedly, though, I enjoy dealing with those pains in Rails. It’s always nice when you can turn an annoying mess into something awesome.
Chris Monday, 08 Oct, 2007 Posted at 12:41PM
The
permissionsmethod passes it’s block to a builder class which has methodspublisherandadministrator, and all those methods do is add a new permission entry to a hash. The actual before filter is like this:The
has_permission?method looks up entries in the permission hash. The key to making this all work easy is that the roles are assigned numerical values, with writer = 0, publisher = 1, and administrator = 2. So, checking the permission entry is like “permission <= current_role” essentially.I can send you the .rb file sometime if you ever want to take a closer look.
Ryan Monday, 08 Oct, 2007 Posted at 01:49PM
Ahh… that’s a clever way to handle the “building” of permissions. Sometimes I’ll browse through random plugin code just to (try and) figure it out… I’m sure I can learn just as much from your stuff… so, send away, I’d love to take a look at it. Thanks!