How to Create Different Permissions Across Users Using Pundit — Ruby on Rails

Russell Sutter
4 min readSep 9, 2020

--

Disclaimer: This guide does not include the use of Devise, which is a common Ruby gem that works well with Pundit.

Pundit is a Ruby Gem that provides developers with the ability to designate certain permissions across different accounts without forcing the developer to create a different model for every different type of user. For example, if you were running a website like Youtube which has a free version and a premium version, you would want users to login in normally and be able to upgrade their account without ever having to make a new account. Another common scenario is, maybe the user needs to go from a basic account, to an admin to manage communities like in Slack or Discord. The Ruby Gem Pundit is a simple, and scalable option that provides Rails developers a set of helpers to help manage who can see what, and who can do what on your application.

For the purpose of this article, I’ll provide a simple demo of how one would go about setting up Pundit. Pundit Docs.

First, install the gem by including gem ‘pundit’ in your Gemfile and by running

rails g pundit:install

in your terminal. This command will not only install the gem but, also create an app/policies directory which, will serve as your base template for creating policies. Next make sure you add include Pundit in your Application Controller.

The initial setup is done. Now we need to figure out how to set roles for our users. We do this by adding a roles column to our Users. If the model already exists, run the command:

rails g migration AddRoleToUsers role:integer

Now our database is setup to store what level of access our User has. Let’s define our users with their respective roles. Obviously we don’t want everyone to have admin access, so we can set this in our User Model.

What’s happening here is we’re enumerating the roles that we set in the users migration because we set them as integers. In the after_initialize method, we’re defaulting all new users to the basic account. To create an admin account, you can create a test User in your seed data where role is set to 1; our admin integer.

Now we have our basic user / admin set up, we can define their permissions. When we ran our rails g pundit:install it created that Application Policy file from which we can inherit from. In that file, you will see a template of what a Class Policy file will look like. Since we’re working with Posts, we’re going to create a PostPolicy. Your PostPolicy should look something like this:

What’s happening here is our PostPolicy is checking to see if the current user has the role of admin. From here you can customize your permissions depending on the users role to tailor towards your application.

Time to put our authorization to the test in our controller. Start by adding after_action :verify_authorized in your Controller and list methods where you want to limit access to specific users.

Now, simply adding authorize @post before our update method will verify that the current user trying to submit a change is an authorized user via our PostPolicy.

If they are not an authorized user, you can set a rescue message that Pundit has built-in in your Application Controller. Here I have Pundit deliver a “Access Denied.” message and redirects them to the previous page, or the designated home page as a fail safe.

If you want to take it one step further you can even show and hide buttons in HTML depending on a users permissions!

Edit / Update function. Image courtesy of Pundit Docs
Here’s a working example for doing a NEW / CREATE for a Product Class I built.

And there you have it! You should now be able to restrict and permit a whole set of users to your liking. You can even build out webpages where you can change a specific users permissions with a simple collection_select button. I encourage a thorough reading of the Pundit Docs to understand this powerful tool, as I only provided a brief and simple understanding. Happy coding!

--

--