Benjamin Curtis

Speculations on Web Development

User Roles in Rails Applications

| Comments

This morning I decided to add roles to CatchTheBest to start adding a few simple permissions to the application. Sometimes people’s eyes glaze over when they hear role-based access control, but it really doesn’t have to be complicated. There are some plugins out there that are more or less plug and play for implementing RBAC, but here’s a quick and simple example you can use in your project to easily add user roles.

First, the migration:

class CreateRoles < ActiveRecord::Migration def self.up create_table :roles do |t| t.column :name, :string end

create_table :user_roles do |t| t.column :user_id, :integer t.column :role_id, :integer t.column :created_at, :datetime end

add_index :roles, :name Role.create(:name => 'Admin')


def self.down drop_table :roles drop_table :user_roles end end

This adds the roles and user_roles tables and creates the first role (Admin). I have added an index to the name field of the roles table because we’ll be querying on that field quite a bit.

Here are the new models:

class Role < ActiveRecord::Base end class UserRole < ActiveRecord::Base belongs_to :user belongs_to :role end

There’s nothing terribly exciting there. :) Notice that I don’t have any relationship declarations in Role, as I currently don’t care about finding users by role — I only care about finding roles by user.

Here are the changes to the User model:

class User < ActiveRecord::Base has_many :user_roles has_many :roles, :through => :user_roles def has_role?(role) self.roles.count(:conditions => ['name = ?', role]) > 0 end

def add_role(role) return if self.has_role?(role) self.roles < < Role.find_by_name(role) end end

And that’s it. Easy, eh?