CanCan is a simple authorization strategy for Rails that is decoupled from user roles. All the permissions are stored in one single location. It is a popular authorization library for Ruby on Rails that restricts user access to specific resources.
Abilities are defined in the
Ability class using
cannot methods. Lets look at the following example:
class Ability include CanCan::Ability def initialize(user) // The visitor and user // A registered user or a new user user ||= User.new can :read, Post // if a user is logged in if user.present? if user.admin? // admins have the privilege to manage everything can :manage, Post can :manage, :all else // other users are given permission to read and edit their own posts. can :read, Post // They cannot read any hidden articles cannot :read, Post, hidden: true end else // user not signed in should view a sign_up page: can :read, :sign_up end end end
Permissions are defined in the Ability class and can be used from controllers, views, helpers, or any other place in the code.
To add authorization support, we first add the
CanCanCan gem to our Gemfile:
Then, we define the ability class:
# app/models/ability.rb class Ability include CanCan::Ability def initialize(user) end end
Secondly, in order to check authorization using
load_and_authorize_resource to load authorized models into the controller, write:
class PostsController < ApplicationController load_and_authorize_resource def show // the post is already loaded and authorized end end
authorize!to authorize or raise an exception.
def show @post= Post.find(params[:post_id]) authorize! :read, @post end
can?to check if an object is authorized against a particular action anywhere in the controllers, views, or helpers.
<% if can? :update, @post%> <%= link_to "Edit", post_path(@post) %> <% end %>
This assumes the signed user is provided by the current_user method. If a user is provided access to update, then that user is provided with a link to edit the post.
CanCan can handle the entire permission logic inside the Ability class, which results in the efficient unit testing of applications.
can? method can be called directly on any Ability so it is easy to test permission logic. Any user can be assigned certain access and any user can be restricted from having certain access. Look at the code below to see how a user can view the post and a restricted user cannot.
test_ability = Ability.new(User.first) test_ability.can?(:show, Post) #=> true other_ability = Ability.new(RestrictedUser.first) other_ability.cannot?(:show, Post) #=> true
View all Courses