Once the number of abilities definitions start to grow in number, it becomes more and more difficult to handle the Ability file.
The first strategy to handle these issue is to move abilities into meaningful methods, as per this example:
class Ability
include CanCan::Ability
def initialize(user)
anyone_abilities
if user
if user.admin?
admin_abilities
else
authenticated_abilities
end
else
guest_abilities
end
end
private
def anyone_abilities
# define abilities for everyone, both logged users and visitors
end
def guest_abilities
# define abilities for visitors only
end
def authenticated_abilities
# define abilities for logged users only
end
def admin_abilities
# define abilities for admins only
end
end
Once this class grow large enough, you can try breaking it into different classes to handle the different responsibilities like this:
# app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
self.merge Abilities::Everyone.new(user)
if user
if user.admin?
self.merge Abilities::Admin.new(user)
else
self.merge Abilities::Authenticated.new(user)
end
else
self.merge Abilities::Guest.new(user)
end
end
end
and then define those classes as:
# app/models/abilities/guest.rb
module Abilities
class Guest
include CanCan::Ability
def initialize(user)
# Abilities for anonymous visitors only
end
end
end
and so on with Abilities::Authenticated
, Abilities::Admin
or any other else.