If you are building a Rails app that has users, chances are you’re going to want to assign users different roles so that you can allow/restrict access to different functions (authorization).
If you’re new to development, it’s probably most intuitive for you to think: I’ll add the role attribute to the User model and set the value to string, so that I can assign roles using strings like: guest, member, or admin. These thoughts are natural, because you’re a human.
That logic does make sense and would work if you implemented it, but it leaves a lot of room for mistakes to be made. Imagine your working really fast and accidentally set a user’s role to “membr” instead of “member”. Yikes! By using the Ruby Enum class, you’re able to use integers to represent user roles. This narrows down the possibilities of errors.
In this example, we could say:
- 0 is a guest user
- 1 is a member user
- 2 is an admin user
The problem with this is that using integers isn’t really intuitive. We’re humans. We want to represent words — like guest, member, and admin — with strings. Enum allows us to reference the user roles with strings, but store them in the database as integers. Best of both worlds!
Quick guide to adding user roles to your app using Enum:
- Start by adding the role attribute to the User model with the following command:
$ rails g migration AddRoleToUsers role:integer
- Add the following line to your User model (
enum role: [:standard, :premium, :admin]
Let’s break this line down:
enumrefers to the Ruby class that we’re using.
role:is the attribute that we’re going to treat as an enum.
[:standard, :premium, :admin]are the names we’re using to reference the user role. Because this is an array, and the index starts at 0, standard role will be stored as 0 in the database, and so on.
- Once you save this, you can open your rails console `rails c`, type User.roles, and it will return a key that will show you which integers correlate with which strings.
- Set a default role for new users by using
after_initializecallback on your User model (
self.role ||= :standard
Now you’re able to use your human sense to set or verify user roles using strings while keeping them nice and tidy stored as integers in the database.
Want to test it?
After you implement the code above. Head over to your rails console and give this a try:
- Grab the first user in your database:
u = User.firstUser Load (0.2ms) SELECT “users”.* FROM “users” ORDER BY “users”.”id” ASC LIMIT ? [[“LIMIT”, 1]]=> #<User id: 1, email: “firstname.lastname@example.org”, created_at: “2018–03–27 06:47:55”, updated_at: “2018–03–27 06:47:55”, role: “standard”>
- Now set that user’s role to admin:
u.admin!(0.1ms) begin transactionSQL (0.8ms) UPDATE “users” SET “updated_at” = ?, “role” = ? WHERE “users”.”id” = ? [[“updated_at”, “2018–03–27 06:50:33.317723”], [“role”, 2], [“id”, 1]](2.0ms) commit transaction=> true
- Check the user’s role and you’ll see that although the role has been stored in the database as
2, Rails will communicate with you like you’re a human!