Rails CanCan refactoring gem Ability клас

Имам около 13 модела в моето приложение за релси, използвам способност на всички тях. Класът ми по способности нарасна огромен. Имам различни условия за способности за различни CRUD действия, което затруднява управлението.

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


person aBadAssCowboy    schedule 20.03.2014    source източник


Отговори (3)


Прост сценарий: Ако можете да разделите разрешенията на няколко взаимно изключващи се комплекта, тогава трябва да проверите това предложение от @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
...

И така нататък за останалите файлове.

person dgilperez    schedule 06.08.2014

Част от решението, споменато тук, е наистина привлекателно. Бих искал да предложа алтернативен метод за справяне с това, където заместваме метода 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 по подразбиране.

В ретроспекция обаче има едно нещо, което трябва да се вземе предвид. Изглежда има два начина да се опитате да мащабирате способностите. По един начин може да имаме много „роли“, на които е разрешено да взаимодействат с данните по различни начини. Другият начин е, че имаме много модели и се нуждаем от начин да разделим логиката там. Този подход работи добре и с двата, защото можете да разделите логиката въз основа на действието, което се предприема (или вероятно ще бъде) предприето.

Друго нещо, можем също да използваме наследяване за предварително зареждане на способности, които са взаимно зависими. Ако Comment принадлежи на Post, тогава CommentsAbility може да наследи от PostsAbility, за да добави необходимата логика.

person William Hatt    schedule 13.12.2015

Можете просто да преместите своя клас на способности към база данни и да управлявате всички разрешения там и да извличате, преди да проверите способността на current_user да извърши действие. Преместването на разрешенията в db не отне много време.

person Ravi D    schedule 20.03.2014