Role-Based Authorization with Rails 4 Enum

I have started creating an employee engagement application recently. Its purpose is to allow companies to engage their employees in volunteering activities around social projects. For this application I need to create 3 different roles and access levels.

I am using Ruby on Rails and I discovered that you could do this with gems such as ActiveAdmin and Rolify. But I decided to give Rails 4 Enum a try.

In my application each User will have one role: a super_admin(that takes care of the whole application), company_admin(an person that administers employee engagement with this application), and employee(user from a company that uses the application). Therefore these are single-defined roles. Now if the User had the possibility to have more than a role, for instance a company_admin could also be a super_admin then this would be a bit more complex. It is indeed multiple role based authorization and the gem Rolify would do a better job at this.

Anyways, below is one way one can implement three different access levels using Enum.

An enumerated-type or enum in Rails is a hash where the values reference to integers in the database. Example

User.access_level # => {"employee"=>0, "company_admin"=>1, "super_admin"=>2}

More info about enum methods here

Assuming that you installed Devise and have a User table or similar, first add the access_level column to the users table

 rails g migration AddAccessLevelToUsers access_level:integer
class AddAccessLevelToUsers < ActiveRecord::Migration 
 def change
   #adding the default to zero will automatically set the user access level to the first Enum attribute
   add_column :users, :access_level, :integer, default: 0

Now in the User Model add:

class User < ActiveRecord::Base
  # you can also explicitly define enum as:  enum access_level: [:employee => 0, :company_admin => 1, :super_admin => 2}
  enum access_level: [:employee, :company_admin, :super_admin]

Migrate the changes to database and create three users in Rails console. Assign them access levels

 # by default the user access_level is employee
 user1.access_level #=> employee 
 # below we are assigning access_level to user2 and user3 rather the default employee

For sanity check, let’s use some conditionals on a page view of your choice to see if it worked.

<% if current_user.super_admin? %>
  <h3>Welcome Super Admin</h3>
<% elsif current_user.company_admin? %>
  <h3>Welcome, Company Admin</h3>
<% else %>
<% end %>

If you sign up as a user3 you should see “Welcome Super Admin” on that page.

This is a simple implementation of single-role-based authorization using Rails 4 Enum. I hope you learned something.

9 thoughts on “Role-Based Authorization with Rails 4 Enum

  1. I’m following your tutorial, as I wanted to learn how to create user authorization from scratch rather than using a gem that does it all for me, but I’m hung up on assigning the users access levels.

    When I type erin = User.find(9) in the console it finds my user. I try to issue the erin.admin! command but it throws an error about the password? (ActiveRecord::RecordInvalid: Validation failed: Password can’t be blank). I’ve also tried erin.access_level = “admin” which returns “admin” while I’m still in the console but no longer exists when I exit the console, fire up the rails server and try to test out my user in my app.

    Is there any other way to assign access levels? Am I just doing it wrong?

  2. This makes much more sense for me than othe info. that i find in internet. Some people say just to create a model fallback for setting the default role to something.

    after_initialize :set_default_role, :if => new_record?

    def set_default_role
    self.role ||= :user

    But for me it is much better to set the default role in the migration like you did.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s