Skip to content

Instantly share code, notes, and snippets.

@mkwiatkowski
Created December 21, 2013 09:30
Show Gist options
  • Save mkwiatkowski/8067287 to your computer and use it in GitHub Desktop.
Save mkwiatkowski/8067287 to your computer and use it in GitHub Desktop.
Annotated ability.rb file
class Ability # Defining a class that will be recognized and used by the CanCan gem.
include CanCan::Ability # Including CanCan::Ability module pulls in the "can" method, so it can be used in the methods of this class.
def initialize(user) # By CanCan convention, currently logged in user (also accessible with "current_user" method in controllers and views) is passed to the initializer.
user ||= User.new # If "current_user" was nil, this will assign a new User object to the "user" variable. New users have no "role" attribute set (i.e. role = nil).
if user.role? :member # Calling "role?" method on user to see if a user has member privileges.
can :manage, Post, :user_id => user.id # To understand the "can" method it's best to read this wiki page: https://github.com/ryanb/cancan/wiki/defining-abilities
can :manage, Comment, :user_id => user.id # In short, this line will allow the user to manage (i.e. do anything with) comments created by her. That's because comments created by given user will have user_id equal to this user's id.
end
if user.role? :moderator # Again calling "role?", this time checking if a user has moderator privileges.
can :destroy, Post # In this case the user will be allowed to destroy all posts, regardless if she created them or not.
can :destroy, Comment # And the same for comments.
end
if user.role? :admin # Finally we check if the user has admin privileges.
can :manage, :all # If so, we give permission to do anything with any object.
end
can :read, :all # The default permission is to allow everyone (also users without a role) to read anything.
end
end
################################################################################
# To understand this particular ability file, you also need to take a look at the definition of "role?" in the User model.
ROLES = %w[member moderator admin]
def role?(base_role)
role.nil? ? false : ROLES.index(base_role.to_s) <= ROLES.index(role)
end
# Just as the description said: The role? method basically answers the question: "Does a user at least have this role?".
# Since there are only three possible values for base_role (member, moderator and admin) and four possible values for the role of the user (the additional fourth being nil) it's easy to walk through all possibilities. Let's do first three.
# If a user has role = moderator in the database, the result of calling role?(:member) on it will be true, since index of the member role in the ROLES array is 0, and index of the moderator is 1. Calling role?(:moderator) will also return true, because 1 <= 1. Finally, calling role?(:admin) will return true, since 2 (index of admin in the ROLES array) is greater than 1 (index of moderator in the ROLES array).
# You can do the same for users with role = member, role = admin and role = nil (guest users).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment