I was recently working on a Rails app that required role-based authorization for its users. Basically, the application would need the ability to check to see if the user had the proper credentials to access certain features of the site.
I’ve typically handled this in the past by either adding an admin
boolean column in the Users
table so I could simply call @user.admin?
to check to see if the user is an admin or not, or for situations which require multiple levels of authorization (or the ability to give a user more than one set of privileges at a time), adding a many-to-many association between the User
model and another model called Role
. This many-to-many association also requires a join table called role_user
. The latter approach is obviously more complex and requires the creation of several helper methods to become convenient to use.
Since I was using Rails 4.1 for this project and because each user only needed to be granted one user role at a time, I figured I would give the new ActiveRecord::Enum
feature a try. Rails now provides a really simple way to quickly add attributes and a bunch of associated helper methods to an Active Record class.
For example, when I added this one line to my User
model:
class User < ActiveRecord::Base enum role: [:reader, :contributor, :admin] end
I got all of these convenience methods for free:
user.contributor! user.contributor? # => true user.role # => "contributor" user.admin! user.contributor? # => false user.admin? # => true user.role # => "admin" User.admin # => relation for all admin users User.roles # => { "reader" => 0, "contributor" => 1, "admin" => 2 }
The only additional thing you need to get these Active Record enums working is a migration to add the attribute to the model, in this case adding role
to User
. Notice that this column is an integer value, which is mapped to the index of each enum value:
$ rails g migration AddRoleToUsers role:integer
which automatically generates:
class AddRoleToUsers < ActiveRecord::Migration def change add_column :users, :role, :integer, default: 0 end end
I also set the first declared status be the default as recommended in the documentation.
And that’s all there is to it! You can find more information in the Rails Edge Guides 4.1 Release Notes.
I think the migration shown there is from another migration, its creating a table called conversations instead of add a role column to the users table.
rails g migration AddRoleToUsers role:integer
create_table :conversations do |t|
t.column :status, :integer, default: 0
end
Thanks for letting me know! This has been corrected.