Rails Can Can Способность класса для нескольких моделей разработки

Мне было интересно, как я могу определить класс способности и служить этому классу способностей в зависимости от пользователя, который вошел в систему.

Я использую Active Admin, Can Can и Devise, и я успешно создал модели User и AdminUser.

У меня это в моих возможностях. rb

class Ability
  include CanCan::Ability

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

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

Теперь я использовал эту запись в вики, чтобы определить, что мы действительно можем определить файл пользовательских способностей и использовать это вместо способности. rb:

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

Но то, что я хотел сделать, - иметь возможность использовать способность .rb, если "пользователь, не являющийся администратором", подписан и пользовательский атрибут, если пользователь зарегистрирован.

Боковой вопрос. Может ли это быть сделано так, что мне не нужен пользовательский, и я могу установить разрешения в одном файле..rb?

Ответ 1

Я никогда не использовал ActiveAdmin, поэтому я не совсем уверен, что мне что-то не хватает, но не похоже, что эта каркас полагается на CanCan. Поэтому я предполагаю, что вы определяете метод current_ability, как описано в вики, и он создается с помощью Ability.new(current_user).

Если этот случай и ваш current_user могут быть либо User, либо AdminUser, тогда нет никакой проблемы при проверке этого в классе 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? в обеих моделях. Это может быть лучшим способом сделать это, поскольку явная проверка типов не очень популярна в рубине - это часто ограничивает ваши варианты. Это может выглядеть так:

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