Reputation: 911
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
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
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
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