Can you CanCanCan?

Zoe Xanos
3 min readJun 11, 2020

It’s been fun experimenting with Rails and everything I can do when building a website. It’s a great feeling to see everything working smoothly, but I’m still only testing out Rails on a localhost. My teachers have talked about implementing code that allows us to control the amount of access granted to each user, but I started wondering if there was a Gem that could help.

I did some searching and found a few Authorization gems like Rolify, but CanCanCan caught my attention. CanCanCan focuses on authorization and specifying what users are and are not capable of. Originally, there was a gem called CanCan by Ryan Bates in 2009. He stopped working on it in 2013, which is when other Rails users took up the code and reworked it into CanCanCan.

From CanCanCan’s github page:

“All permissions can be defined in one or multiple ability files and not duplicated across controllers, views, and database queries, keeping your permissions logic in one place for easy maintenance and testing.

It consists of two main parts:

Authorizations library that allows you to define the rules to access different objects, and provides helpers to check for those permissions.

Rails helpers to simplify the code in Rails Controllers by performing the loading and checking of permissions of models automatically and reduce duplicated code.”

As an example, if an app is capable of sending messages between two users, we need to be sure that only the two users in conversation can view this data.

To use CanCanCan, add this to your gem file:

gem 'cancancan'

And run the usual bundle install in terminal.

If we use an example of a blogging website, CanCanCan is able to understand the difference between an author of a post, a separate user, and an admin. Authors and Admins can be given privileges to a post that a casual user cannot. In the same way I can only edit my posts, if I view someone else’s blog, I am not allowed to edit or delete that person’s blog post.

This is an example of implementation from CanCanCan’s github:

class Ability
include CanCan::Ability

def initialize(user)
can :read, Post, public: true

if user.present? # additional permissions for logged in users (they can read their own posts)
can :read, Post, user_id: user.id

if user.admin? # additional permissions for administrators
can :read, Post
end
end
end
end

Can or Cannot?

Part of implantation is a check for what a particular user viewing a page can or cannot do.

<% if can? :read, @post %>
<%= link_to "View", @post %>
<% end %>

If this user is allowed or ‘can? == true’ read this post, then link them to View the post.

There are also checks on CRUD:

can? :create
can? :read
can? :update
can? :destroy

There is an authorize method available in Controller

def show
@article = Article.find(params[:id])
authorize! :read, @article
end

There are even more options beyond what I could find but looking into this gem made me realize what I need to consider when creating websites using Rails.

While CanCanCan is a great way to practice Authorization on a small scale, I have seen reports of CanCanCan slowing down the site because of how it checks authorization through an ability file. I have seen work arounds for this as well, but testing CanCanCan is the one way to know for sure what you are looking for. Beyond CanCanCan there are still more gems available to optimize Authorization:

Pundit
Rolify
Authority
Canard

As our work becomes more and more complex, I want to test the concept of multiple users and deciding what a user can or cannot do.

--

--