Library / SDK
CanCanCommunity/cancancan avatar
CanCanCommunity/cancancan

CanCanCan: rule-based authorization for Ruby on Rails

The authorization Gem for Ruby on Rails.

5,682 stars629 forksRubyMIT

At a glance

What is it?
CanCanCan keeps permission logic in Ability classes and exposes it through can?, authorize! and accessible_by. Here is how the pieces fit, what the controller helpers hide, and when Pundit is the better fit.
Who is it for?
Adopt CanCanCan when permissions are naturally expressed as rules over models and you want the same rules to filter database queries through accessible_by, which is the capability the README singles out against other authorization libraries. Do not adopt it when your authorization is mostly per-action policy objects with their own tests, since that is what Pundit models and CanCanCan does not.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 21 days ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The duplication problem CanCanCan removes

Authorization code drifts. A controller checks one condition, a view renders a link under a slightly different condition, and a scope on the index action applies a third. CanCanCan's answer is to define permissions once in an Ability class and derive everything else from that definition. The README states this directly: permissions are defined in one or multiple ability files "and not duplicated across controllers, views, and database queries." The audience is Rails teams that already have models and controllers and want a single place to read when asking who may do what. It is not a role system. There is no roles table, no assignment UI, no admin panel. Roles enter only as whatever your user object exposes, and the README's example calls user.admin? and user.present? on the object passed to the Ability constructor. If you need role storage and assignment, that is a separate concern you bring yourself.

Ability rules, can? checks and accessible_by

The library has two parts, per the README: an authorizations library that defines rules and provides helpers to check them, and Rails helpers that load and check models in controllers. Rules are declared with can inside a class that includes CanCan::Ability. The README's example shows three layers in one initialize method: can :read, Post, public: true for anonymous visitors, then a return unless user.present? guard, then can :read, Post, user: user for logged-in owners, then a return unless user.admin? guard before can :read, Post with no conditions. The conditions hash is not decoration. It is the bridge to the database. Post.accessible_by(current_ability) turns the same rules into a query, so the index action returns only rows the user may read. That is the mechanism the README calls out as a key feature compared to other authorization libraries: permissions are not just booleans checked after loading a record, they also generate the scope. The trade-off is that anything the rules cannot express as a database condition has to be handled in Ruby, and the README does not describe how accessible_by handles rules whose conditions cannot be translated.

Installing CanCanCan and writing a first Ability

The README gives two installation steps. Add the gem to the Gemfile, then run bundle install.

ruby
gem 'cancancan'
bash
bundle install

After that, generate the Ability class with the Rails generator named in the README.

bash
rails g cancan:ability

The generated class is where rules live. This is the README's own example, defining read access for the public, for a post's owner, and for administrators.

ruby
class Ability
  include CanCan::Ability

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

    return unless user.present?
    can :read, Post, user: user

    return unless user.admin?
    can :read, Post
  end
end

Two checks follow from that. In a view or controller, can? :read, @post returns a boolean for the current user. In a controller action, authorize! :read, @post raises an exception when the check fails, which is what you rescue to render a 403 rather than a 500.

ruby
def show
  @post = Post.find(params[:id])
  authorize! :read, @post
end

For a RESTful controller, the README offers load_and_authorize_resource as a before action that loads the resource into an instance variable and authorizes it for every action, so show gets @post already loaded and index gets @posts already filtered. What you should see after adding it is that the manual find and authorize calls disappear from the actions.

Where load_and_authorize_resource gets in the way

The convenience is also the sharp edge. load_and_authorize_resource assumes a conventional RESTful controller: a model name derivable from the controller, an instance variable named after it, and actions that map cleanly onto load-then-authorize. The README documents it in exactly those terms, as a method for "a RESTful style resource controller." Controllers that do not fit, such as ones serving multiple models, actions that operate on a collection rather than a member, or endpoints where the resource is fetched through a join or an external service, force you to fight the implicit loading or fall back to explicit authorize! calls. The README does not document rollback or an opt-out per action beyond the general implication that you can skip the helper entirely. The second limitation is that a single Ability class grows with the application. The README allows multiple ability files, but it does not prescribe how to split them, so the boundary between them is a design decision you make and document yourself. Teams that skip that decision end up with the same tangled permission logic they adopted the gem to remove, just in a different file.

CanCanCan versus Pundit

The comparison people actually search for is CanCanCan against Pundit, and the difference is structural rather than cosmetic. Pundit organizes authorization as one policy class per model, with one method per action, instantiated with a user and a record. CanCanCan organizes it as rules declared with can inside a single Ability class, evaluated against actions and subjects. The practical consequence is the query side. CanCanCan's accessible_by derives a relation from the rules, which is why the README presents fetching authorized records as its distinguishing feature. Pundit's policy methods return booleans over an already-loaded record, leaving scope construction to separate scope classes you write. If your index actions need to filter at the database level from the same source of truth as your checks, CanCanCan's model is a shorter path. If you prefer per-action methods that are individually testable and read like the action they guard, Pundit's shape is closer to that. Neither is a superset of the other, and the choice mostly follows from whether your permissions are easier to state as rules over models or as methods over actions.

Maintenance, Rails versions and the MIT licence

The repository is not archived, and the last push was on 2026-09-08. The newest release listed is 3.5.0 from 2023-03-05, with 3.4.0 and 3.3.0 before it in 2022. That gap between the last push and the last release is worth reading correctly: commits continue, tagged releases are less frequent, so pinning to a release means you are not tracking the develop branch. The default branch is develop, which is where that activity lands. Upgrade cost is dominated by Rails compatibility. The README describes development with appraisals, testing the code base against multiple versions of Rails and different model adapters, and gives commands such as bundle exec appraisal install and DB='sqlite' bundle exec appraisal activerecord_5.2.2 rake. The Appraisals file and the gemfiles directory are the authoritative list of what is tested; check them against your Rails version before upgrading, since a combination absent from that matrix is untested by the project's own suite. The licence is MIT. That permits commercial use and modification, and it comes with no warranty, but this is a description of the licence identifier rather than legal advice; read the LICENSE file for the terms that apply to you.

Editorial conclusion

Adopt CanCanCan when permissions are naturally expressed as rules over models and you want the same rules to filter database queries through accessible_by, which is the capability the README singles out against other authorization libraries. Do not adopt it when your authorization is mostly per-action policy objects with their own tests, since that is what Pundit models and CanCanCan does not. Before committing, verify the Rails version your application runs against the Appraisals file and gemfiles directory, because the repository tests against a fixed matrix of Rails and adapter combinations rather than an open-ended range, and check the CHANGELOG for the 3.5.0 release notes since that is the newest release listed.

Frequently asked questions

What is the CanCanCan gem?

It is an authorization library for Ruby and Ruby on Rails that restricts which resources a user may access. Permissions are defined in Ability classes, and the library provides helpers such as can?, authorize! and accessible_by to check and apply them.

How do I install CanCanCan in a Rails app?

Add gem 'cancancan' to your Gemfile and run bundle install, then generate the Ability class with rails g cancan:ability. Rules are declared inside that class with the can method.

What does accessible_by do in CanCanCan?

It uses your Ability rules to return only the records the user is authorized to access, so Post.accessible_by(current_ability) yields the list of posts the current user can read. The README presents this as a key feature compared to other authorization libraries.

What is the difference between CanCanCan and Pundit?

CanCanCan defines permissions as rules in an Ability class and can derive database queries from them through accessible_by. Pundit uses policy classes with methods that check an already-loaded record, leaving authorized-scope construction to code you write separately.

Official sources

  1. CanCanCommunity/cancancan on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/cancancommunity-cancancan.svg)](https://hysenlabs.com/projects/cancancommunity-cancancan)