Rails CanCan为多个Devise模型提供的Ability类

10

我想知道如何定义一个能力类,并根据已登录的用户提供该能力类。

我正在使用Active Admin、Can Can和Devise,我已成功创建了User和AdminUser模型。

以下是我在ability.rb中的代码:

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new

    if (user)
      can :manage, Item
    end
  end
end

现在我已经使用这个wiki页面来确定我们确实可以定义一个自定义的ability文件,并使用它来代替ability.rb:

https://github.com/ryanb/cancan/wiki/changing-defaults

但是我想做的是,当“非管理员用户”登录时使用ability.rb,当管理员用户登录时使用自定义的ability。

附带问题:是否可以这样做,以便我不需要自定义文件,并且可以在一个ability.rb文件中设置权限?


啊,你说得对。我没有注意到你已经为用户和管理员用户使用了不同的类。你应该能够更改Active Admin使用的类,但我不是该系统的用户,所以不确定具体在哪里更改。可能应该检查一下你的初始化程序。 - jdl
1个回答

12

我从未真正使用过ActiveAdmin,所以我不确定是否遗漏了什么,但它似乎并不依赖于CanCan框架。这就是为什么我假设您正在按照维基中所述定义current_ability方法,并使用Ability.new(current_user)进行实例化。

如果情况如此,且您的current_user可以是UserAdminUser,则在Ability类中检查这一点是没有问题的:

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new

    if user.kind_of? AdminUser
      can :manage, Item
    elsif user.kind_of? User
      can :read, Item
    end
  end
end

你可以简单地查看用户类型并相应地更改规则。你也可以使用is_a?代替kind_of?进行严格的检查,但这可能并不需要,并且如果以后决定进行继承,则可能会引起问题。

另一种检查方式是在两个模型中定义一个admin?方法。这可能是更好的方法,因为在Ruby中显式类型检查并不常见--它经常限制你的选择。它可能看起来像这样:

class User < ActiveRecord::Base
  def admin?
    false
  end
end

class AdminUser < ActiveRecord::Base
  def admin?
    true
  end
end

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new

    if user.admin?
      can :manage, Item
    else
      can :read, Item
    end
  end
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接