How would I go about defining abilities for several devise models?
Let's assume your app has two separate Devise-powered user models called User
and Admin
. This means you use methods like current_user
and current_admin
side by side.
Let's further assume that you only have/want a single Ability
class, which contains all your CanCan permission settings...
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
case user
when User
can :create, Comment
can :read, :all
when Admin
can :manage, :all
end
end
end
This is exactly what others have proposed, but there's another step you have to take.
By default, CanCan assumes that the method current_user
exists and will return a User object to compare with your Ability
settings. However, our admin users can be found using current_admin
. Without telling CanCan where to find admin objects, they never get reviewed, and thus never get permissions; we must change the defaults when dealing with an admin.
Add the following to application_controller.rb
...
def current_ability
if admin_signed_in?
@current_ability ||= Ability.new(current_admin)
else
@current_ability ||= Ability.new(current_user)
end
end
Now our Ability class will look at the Admin object if one is available, and fall back on a normal User when none is present.
Further development allows us to move Admin permissions into their own separate Ability class...
def current_ability
if admin_signed_in?
@current_ability ||= AdminPowers.new(current_admin)
else
@current_ability ||= Ability.new(current_user)
end
end
For more info, see Changing Defaults in the Wiki. Kudos to Stefan for pointing me at the proper article.
FYI -- CanCan is dead, long live CanCanCan! Up to date with bug fixes and new features. Same namespaces, so it's just a drop-in gem replacement in your Gemfile.
gem 'cancancan', '~> 1.8'
This worked for me -
class Ability
include CanCan::Ability
def initialize(user)
if user.is_a?(Admin)
can :manage, :all
elsif user.is_a?(User)
can :create, Comment
can :read, :all
else
can :read, :all
end
end
end
The current user model is passed to the Ability#initialize
, so you can just check its class:
class Ability
include CanCan::Ability
def initialize(model)
case model
when Admin
can :manage, :all
when User
can :create, Comment
can :read, :all
else
can :read, :all
end
end
end
Ability#initialize
is not being called for your Admin. Add some logging and check out Changing Defaults. –
Scorpius © 2022 - 2024 — McMap. All rights reserved.