Trusted answers to developer questions

How to define abilities in CanCan

Get Started With Machine Learning

Learn the fundamentals of Machine Learning with this free course. Future-proof your career by adding ML skills to your toolkit — or prepare to land a job in AI or Data Science.

CanCan is an authorization library for Ruby on Rails that defines the authorization of specific resources for multiple users. All these permissions are set in a single locality (the Ability class) and are not duplicated across controllers, views, or database queries.

Below is an example of the Ability class:

class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.admin?
can :manage, :all
else
can :read, :all
end
end
end

The current user model is passed into the initialize method to ensure that the permissions can be modified based on user attributes. No assumption takes place in the handling of roles.

Can method

The permissions are set using the can method, which requires two arguments:

can action, object

where:

  • action is the action you are setting the permissions for
  • object is the class of the object you are setting it on

The action can be commonly set to:

  • :manage to represent any action
  • :read to allow the user to read the following object
  • :create to enable the user to create the next object
  • :update to allow the user to update the resulting object
  • :destroy to allow the user to delete the following object

The object can be set to include any class:

  • all can be set to apply the action to any object

The object and action can be passed as an array as well. This sets permissions for all objects and all actions.

can [:create, :destroy] , [Article, Comment]

Here, the user will be able to create and destroy both Article and Comments.

Note: If you apply :manage to an object, it sets all permissions, not just :read, create, :update, and :destroy.

If you only want to allow given permissions to be set when :manage is called, you can create a custom action:

def initialize(user)
  user ||= User.new

  alias_action :create, :read, :update, :destroy, :to => :custom
 
  can :custom, User
  can :invite, User
end

Now, the :invite permissions are not set by default.

It is possible to define multiple abilities for the same resource:

can :destroy, Project, :deprecated => true
can :destroy, Project, :published => true

Here, the user is able to destroy all projects that have been published or deprecated.

Cannot method

The cannot method takes the same arguments as can and defines the actions the user is unable to perform.

This can be used to edit permissions after a generic call:

can :manage, Project
cannot :destroy, Project

The order of these calls is important.

Hash of conditions

A hash can be used to further restrict the record. An example of what these permissions apply to are:

can :read, Project, :user_id => user.id

Here, the user is only allowed to read projects that are owned by the user.

Note: Ensure that the columns used here are same as the column names in the database.

Nested hashes can also be used on the given conditions, like:

can :update, Project, :category => { :visible => true }

Here, the Project can only be edited if the category it belongs to is visible.

Furthermore, a range can be passed to set permissions for multiple values:

can :update, Project, :version => 1..3

However, this will not apply to model objects. For those, you will need to apply:

can :update, Project, :group => { :id => user.groups_ids }

RELATED TAGS

cancan
abilities
Copyright ©2024 Educative, Inc. All rights reserved
Did you find this helpful?