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 Abilityinclude CanCan::Abilitydef initialize(user)user ||= User.new # guest user (not logged in)if user.admin?can :manage, :allelsecan :read, :allendendend
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.
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 forobject
is the class of the object you are setting it onThe 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 objectThe object
can be set to include any class:
all
can be set to apply the action to any objectThe 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.
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.
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 }
Free Resources