Rails CanCan gam refactoring Класс умения

У меня около 13 моделей в моем приложении rails, я использую способность на всех из них. Мой класс умений вырос. У меня разные условия для различных действий CRUD, которые затрудняют управление.

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

Ответ 1

Простой escenario. Если вы можете разделить разрешения в нескольких взаимоисключающих наборах, вы должны проверить это предложение от создателя @ryanb, CanCan, в котором он разделяет способности на несколько разных классов, а затем перезаписывает метод current_ability в ApplicationController

Как вы можете разбить большой класс умения в CanCan-Gists

Более сложный сценарий. Если у вас есть несколько разных перекрывающихся наборов разрешений, вы можете попробовать этот подход:

# app/models/ability.rb

class Ability
  include CanCan::Ability

  def initialize(user)
    self.merge Abilities::Everyone.new(user)

    if user
      self.merge Abilities::Admin.new(user) if user.admin?
      self.merge Abilities::Authenticated.new(user)
    else
      self.merge Abilities::Guest.new(user)
    end
  end
end

# app/models/abilities/admin.rb
module Abilities
  class Admin
    include CanCan::Ability

    def initialize(user)
      # define abilities here ...
    end
  end
end

# app/models/abilities/everyone.rb
...

И так далее для остальных файлов.

Ответ 2

Часть упомянутого здесь решения действительно привлекательна. Я хотел бы предложить альтернативный метод для обработки этого, где мы переопределяем метод current_ability в application_controller, чтобы сделать его динамическим в зависимости от используемого контроллера. Оттуда мы можем указать возможность использования в каждом контроллере. Это может выглядеть примерно так:

./app/abilities
              ./posts_ability.rb
              ./comments_ability.rb
              ./admin_ability.rb
              ./pictures_ability.rb
              ./uploads_ability.rb

Затем в. /app/controllers/my _controller.rb это будет выглядеть так:

class MyController < ApplicationController
    authorize_with PostsAbility
end

Он также может оказаться автоматически, когда PostsController будет использовать PostsAbility по умолчанию.

В ретроспективе, однако, есть одна вещь, которую следует рассмотреть. Кажется, есть два способа попытаться масштабировать способности. В одном случае у нас может быть много "ролей", которым разрешено взаимодействовать с данными по-разному. Другой способ заключается в том, что у нас много моделей и нам нужен способ разделить логику там. Этот подход хорошо работает с обоими из них, потому что вы можете разделить логику на основе действия, которое (или, вероятно, будет) принято.

Еще одна вещь, мы также можем использовать наследование для способностей до загрузки, которые являются зависимыми друг от друга. Если комментарий принадлежит сообщению, то функция CommentAbility может унаследовать от PostsAbility, чтобы добавить необходимую логику.

Ответ 3

Вы можете просто переключить свой класс возможностей на базу данных и управлять всеми разрешениями там и выполнить выборку, прежде чем проверять способность текущего_узыка выполнять действие. Он не занимает много времени при перемещении разрешений на db.