How to integrate CanCan with multiple devise models?

后端 未结 3 1456
感情败类
感情败类 2021-01-02 01:22

How would I go about defining abilities for several devise models?

相关标签:
3条回答
  • 2021-01-02 01:29

    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
    
    0 讨论(0)
  • 2021-01-02 01:49

    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'
    
    0 讨论(0)
  • 2021-01-02 01:53

    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
    
    0 讨论(0)
提交回复
热议问题