I'm building authorization in my app and have three roles:
What's the best way to represent this in Rails? I've thought about adding the following boolean fields to my user's table:
And then creating is_user?
, etc functions in the User model.
A user can have multiple roles (can be all three).
I suggest to use bitwise values for your access levels. This is valid because you have a limited number of roles and because your users can have several roles at once.
It is way much faster and easier to maintain than to use an external gem.
The idea is to use a numeric value for each access level, which can be accumulated at the bit level.
Level | Int val | Bit val
user | 1 | 00000001
moderator | 2 | 00000010
admin | 4 | 00000100
another | 8 | 00001000
etc ... | 16 | 00010000
So a user and a moderator would have a access level of 1 + 2 = 3 (bit 00000011). Then we can test for the bit values to define the user access_level
1) Add a access_level
column in your user model, of type integer and default 0
2) Set constants to define your access level values
class User < ActiveRecord::Base
USER = 1
MODERATOR = 2
ADMIN = 4
end
3) Create the add_access_level
and remove_access_level
methods
class User < ActiveRecord::Base
# Add the desired bit
def add_access_level(level)
self.access_level |= level
end
# Removed the desired bit
def remove_access_level(level)
self.access_level &= ~level
end
end
Note: Up to you to persist those changes in the database
4) Create the is_user?
, is_moderator?
and is_admin?
methods
class User < ActiveRecord::Base
def is_user?
is_access_level? USER
end
def is_moderator?
is_access_level? MODERATOR
end
def is_admin?
is_access_level? ADMIN
end
private
def is_access_level?(level)
self.access_level & level == level
end
end
Note: I would be using method_missing
, but this is out of our scope here.
5) Test it
u = User.new
u.is_admin?
=> false
u.is_moderator?
=> false
u.is_user?
=> false
u.add_access_level User::USER
u.add_access_level User::MODERATOR
u.is_admin?
=> false
u.is_moderator?
=> true
u.is_user?
=> true
u.remove_access_level User::MODERATOR
u.is_admin?
=> false
u.is_moderator?
=> false
u.is_user?
=> true