parm530
11/8/2017 - 3:22 PM

CanCan Gem

Understanding how to use the cancan gem for authentication

CanCanCan is a continuation for the no longer maintained gem CanCan

AUTHENTICATION

Set up

  • In Gemfile, add gem 'cancancan'
  • Run bundle install
  • To generate the Ability class: rails g cancan:ability

In your controller, it looks like this:

def show
  @article = Article.find(params[:id])
  authorize! :read, @article
end
  • In this action, authorize is being called to see if the user can read this article, if not an exception is thrown.
  • If you require this authorization in all your actions, an easier way to write this such that all your actions will
  • will have authorized the user is to place this line at the top of the controller class:
class ArticleController < ApplicationController
  load_and_authorize_resource
  
  def show
    # @article is already loaded and authorized
  end
end
  • If the authorization fails, a CanCan::AccessDenied exception will be raised! You can catch this and modify its behavior in the ApplicationController:
class ApplicationController < ActionController::Base
  rescue_from CanCan::AccessDenied do |exception|
    respond_to do |format|
      format.json { head :forbidden }
      format.html { redirect_to main_app.root_url, :alert => exception.message }
    end
  end
end
  • In your views, this might look like:
<% if can? :update, @article %>
    <%= link_to "Edit", edit_article_path(@article) %>
<% end %>

# OR it can look like this:
<% if cannot? :update, @article %>
  Editing disabled.
<% end %>
  • To generate the ability file, run:
rails g cancan:ability
  • This creates an ability.rb file in models directory with and Ability class inside
  • In this class, you can define the permissions:
class Ability
  include CanCan::Ability
  
  def initialize(user)
    if user.admin?
      #only admins can change this
      can :update, Article
    end
    # anyone can read
    can :read, Article
  end
end
  • The ability class is passed an instance of your User model by calling the current_user method.
  • In the initializer, you call can or cannot to define what this particular user can do!
  • can or cannot both take the following arguments:
    • the action (written as a symbol)
    • an ActiveRecord class, an instance of which is the target of the action
  • You can be more specific if you want to allow (or disallow) the user