user3304086
user3304086

Reputation: 911

Best practice to declare different user roles?

I want to declare different user roles on my site and I was wondering what is the best practice to do it in Rails? For now I have two options:

OPTION 1:

I create table Users and declare one string column where I can store names of user roles (SuperAdmin, Admin, Coach, Player)

create_table "users", force: true do |t|
    t.string   "username"
    t.string   "first_name"
    t.string   "last_name"
    t.string   "email"
    t.string   "role"
end

Inside User class I save the values like this:

class User < ActiveRecord::Base
  ROLES = %w[SuperAdmin, Admin, Player, Coach]
end

OPTION 2:

I create a separate table only for roles. Inside Users table I have integer column for storage of role_id:

create_table "users", force: true do |t|
    t.string   "username"
    t.string   "first_name"
    t.string   "last_name"
    t.string   "email"
    t.integer  "role_id"
end

create_table "roles", force: true do |t|
    t.string   "role_name"
end

class User < ActiveRecord::Base
  belongs_to :role
end

class Role < ActiveRecord::Base
  has_many :users
end

What would be a better option when if we take search speed, addition of new roles and future maintenance into the consideration?

Upvotes: 5

Views: 1335

Answers (3)

Richard Peck
Richard Peck

Reputation: 76784

IMO the best way is to use a standard has_many belongs_to relationship between a User and Role model:

#app/models/user.rb
Class User < ActiveRecord::Base
   belongs_to :role

   before_create :set_role

   def set_role
       role = self.role_id
       role_id = "0" unless defined?(role)
   end 
end

#app/models/role.rb
Class Role < ActiveRecord::Base
   has_many :users
end

users
id | role_id | name | created_at | updated_at

roles 
id | name | created_at | updated_at

This will allow you to associate users to a specific role, and continue to add / adapt the roles as required

Upvotes: 0

Alessandro De Simone
Alessandro De Simone

Reputation: 4215

Create an other table to store the role is an over engineered solution :)

Use the gem cancan is a good approach, you need just to add a field to the user model. With cancan you can even assign multiple roles to a user and store it into a single integer column using a bitmask.

Upvotes: 0

marvelousNinja
marvelousNinja

Reputation: 1510

Basic variant:

class User < ActiveRecord::Base
  has_and_belongs_to_many :roles
end

class Role < ActiveRecord::Base
  has_and_belongs_to_many :users
end

class CreateRolesUsersJoinTable < ActiveRecord::Migration
  def change
    create_table :roles_users, id: false do |t|
     t.integer :user_id
     t.integer :role_id
    end
  end
end

Here's why: you don't want has_many with roles, cause you won't be able to associate the same role with different users. It is a typical HABTM relationship. Yes, later it can become a performance problem, since it can be pretty hard to fetch all roles with associated records for every user. Then you will look into other variants for optimization: bitmaps, intensive caching or something else.

Hope you find it useful.

Upvotes: 3

Related Questions