【问题标题】:Is it possible to use cancan with two ability class是否可以使用具有两个能力等级的康康
【发布时间】:2012-10-05 14:07:12
【问题描述】:

我正在使用 rails 3.0.9、cancan 1.6.7 和设计 1.4.8

我使用两个设计模型(用户和管理员)进行不同的登录和注册过程

所以我想根据登录用户(资源)来划分能力,因为有超过 70 个模型和只有 10 个模型对两种类型的用户都是通用的(这里 50 多个模型和视图仅供管理员用户使用)

我想实现两个能力类(UserAbility 和 AdminAbility),并且设计辅助方法 current_user/current_admin 应该传递给 UserAbility/AdminAbility

例子:

在 ApplicationController.rb 文件中

    def current_ability
        if current_user
            @current_ability = UserAbility.new(current_user)
        elsif current_admin
            @current_ability = AdminAbility.new(current_admin)
        end
    end

根据以上我的问题,

  1. 在cancan中是否可以使用多个能力类,如果可以,那么如何创建它,因为我尝试过

    rails g cancan:user_ability

    但我得到了错误,因为 找不到生成器 cancan:user_ability

  2. 如何为登录的用户/管理员选择合适的能力等级。

  3. 如果用户和管理员都访问了一个控制器,那么如何获取当前登录的用户/管理员的对象

还有其他解决办法吗?

请大家帮忙解决一下

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 devise cancan


    【解决方案1】:

    ...也就是说,如果您愿意,可以直接使用多个能力模型:

    class UserAbility
      include CanCan::Ability
    
      def initialize(user)
        can :read, :all
      end
    end
    
    class AdminAbility
      include CanCan::Ability
    
      def initialize(admin)
        can :manage, :all
      end
    end
    
    class ApplicationController < ActionController::Base
      # overriding CanCan::ControllerAdditions
      def current_ability
        if current_account.kind_of?(AdminUser)
          @current_ability ||= AdminAbility.new(current_account)
        else
          @current_ability ||= UserAbility.new(current_account)
        end
      end
    end
    

    【讨论】:

    • 是的,我只为此尝试过,但我尝试了很多来创建另一个 cancan 能力类,但我不能(可能是我不知道正确的语法)
    • 您不需要生成器 -- 只需在 app/modelsinclude CanCan::Ability 中创建一个新文件。
    【解决方案2】:

    你不需要多个能力等级:

    class Ability
      include CanCan::Ability
    
      def initialize(user_or_admin)
        user_or_admin ||= User.new
    
        common_rules(user_or_admin)
    
        if user_or_admin.kind_of? Admin
          admin_rules(user_or_admin)
        else
          user_rules(user_or_admin)
        end
      end
    
      def common_rules(user_or_admin)
        # can :verb, :noun
      end
    
      def admin_rules(admin)
        can :manage, :all
      end
    
      def user_rules(user)
        can :read, :all
      end
    end
    

    CanCan 最终将使用任一模型调用Ability.new(),但这很好,因为您可以检查收到的对象类型。当然,如果您愿意,也可以委托给其他对象;一切都只是 Ruby。

    【讨论】:

    • 谢谢@willglynn,我会去的,请告诉我,是否可以调用一个帮助方法,该方法在每次查看时返回当前登录的用户/管理员的对象,或者有任何其他的获取此对象的方法
    • 这取决于您的应用程序的其余部分。这当然是可能的,但我不能告诉你怎么做。
    • 优雅的解决方案。整洁
    • 如果您的单个 ability.rb 文件变得笨拙,请查看将它们分成单独的文件,如下所示:stackoverflow.com/questions/7738376/…
    【解决方案3】:

    我已经实现了@willgiynn's 解决方案的一部分,修改了application_controller.rb 中的current_ability 方法。

    关于ability.rb

    class UserAbility
      include CanCan::Ability
    
      def initialize(user)
        can :read, :all
      end
    end
    
    class AdminAbility
      include CanCan::Ability
    
      def initialize(admin)
        can :manage, :all
      end
    end
    

    打开 application_controller.rb

    def current_ability
      @current_ability ||= current_admin ? AdminAbility.new(current_admin) : UserAbility.new(current_user)
    end
    

    希望对你有帮助!

    【讨论】:

      【解决方案4】:

      我将添加到 willgiynn has answered 的内容。看来我必须添加更多代码才能使其正常工作。我从这个post找到了答案

      将以下内容添加到 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-10-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多