views:

67

answers:

2

My application has 2 roles: Editor, and Admin. I want Editors to have some permissions, and Admins to have all editor permissions plus some other permissions.

Here is an excerpt from my ability.rb

class Ability
  include CanCan::Ability

  def initialize(user)
    if user.is_admin?
      can :edit, Post
    end

    if user.is_editor?
      can :edit, Post, :created_by_id => user.id
      can :read, Post
    end
  end
end

Since all admins are also editors, I hoped this would define these permissions:

  • Admins can read and edit all posts
  • Editors can read all posts, but only modify those which they created

However, CanCan doesn't seem to define permissions additively – i.e., when CanCan sees that a user is an Editor (even if the user is also an admin), it applies the more restrictive permission (i.e., can :edit, Post, :created_by_id => user.id instead of can :edit, Post).

Is there any way around this? The obvious solution requires repeating code:

class Ability
  include CanCan::Ability

  def initialize(user)
    if user.is_admin?
      can :edit, Post
      can :read, Post # NOT DRY!!!
    elsif user.is_editor?
      can :edit, Post, :created_by_id => user.id
      can :read, Post
    end
  end
end
A: 

Why don't you just redefine the edit alias? You can also do:

can [:edit, :read], Post
Tony
+2  A: 

Have you tried authorizing with a block?

can :edit, Post do |post|
 post.created_by_id == user.id || user.is_admin?
end

if user.is_editor?
  can :read, Post
end
Zachary