Sometimes we forget that Ruby on Rails is in fact built on … Ruby. In this post, I want to explore the CanCan gem to see how it works its magic.
This post explores how the CanCan gem (v1.6.10) works internally. Lots of this applies to other gems as well.
If you’re completely unfamiliar with CanCan, the authorization gem from Ryan Bates, I highly recommend you look it up. Very briefly, this gem allows me to write code such as this:
1 2 3
How simple is that?
On the flip side, the user abilities are defined like this:
1 2 3 4 5 6 7 8 9 10
user param that you see passed into the
initialize method is the result of querying a global
It is your responsibility to create that method, and ensure it return the logged in user. Cancan handles authorization, not authentication.
In these lines of code, we allow the
:edit an instance of the
Article model if the
author_id property on the Article matched the
id of the user.
There are lot’s of other options here, so read the well-written wiki.
Make sure you create this class, and name it
Ability. CanCan relies on that convention.
So how does the magic happen? How do we have access to this new method
As is the case of any gem, when you add
gem 'cancan' to your Gemfile, and run
bundle, ruby will fetch the gem source-code if doesn’t exist on your system yet, and will load the file in the lib/GEM_NAME.rb, in this case
You’ll see that this file simply requires the rest of the gem’s code, all in the
lib dir, namespaced under the
The first file required is
ability.rb. This is the file that declares the
CanCan::Ability module, which as seen before will get
included in our
The methods defined in this module are what we can call in our
Ability file, such as
can :edit, Article, author_id: user.id.
The next file,
rule.rb, is what handles a lot of the dirty work under the hood. The methods in this file are all for internal use only. This gem has been designed so as to completely isolate code meant to be called directly (such as the
authorize methods) from these methods, which are never meant to be directly referenced.
So it is with the next two required files,
controller_additions.rb, the former of which is the internal implemention of the latter. It is within this latter file that we see the
can?, and other methods that get called within our views and controllers.
So how do we actually have access to these methods without adding any
extend calls into our model or controller classes?
The magic happens in the last few lines:
1 2 3 4 5
This checks if we’re using Action Controller, and if we are, it
includes this module into the
ActionController::Base, the module which the
ApplicationController inherits from, which in turn, is the class from which all other controllers inherit.
But to get access to the
can and other methods which are defined in
CanCan::ControllerAdditions::ClassMethods module, we need this bit of code:
1 2 3 4
extends all our application controllers (by way of inheriting from
ActionController::Base), and gives them the ability to respond to those method calls.
It also calls the
helper_method method passing in the
:current_ability methods, giving our views access to those methods as well.
So that’s the short of it. Although the wiki is very helpful, the inline documentation is more verbose, so if you get stuck, that might be a good place to start. Besides, code organization is a skill hard to pickup, and I’m sure I’ve learned something perusing this codebase, written by a programmer far more skilled than me. And, best of all, Rails is that much less magical. Magic != Fun.
All Revisions to this document are visible here