Rails CanCan宝石重构能力等级

时间:2014-03-20 11:00:29

标签: ruby-on-rails ruby ruby-on-rails-4 rubygems cancan

我的rails应用程序中有大约13个模型,我使用了所有这些模型的能力。我的能力课程变得越来越大。我对不同的CRUD操作有不同的能力条件,这使得难以管理。

有人可以指导我如何重构这个......?比如,使用模块或类来使我的能力课看起来很整洁。

3 个答案:

答案 0 :(得分:16)

简单的场景:如果你可以在几个互斥的集合中拆分权限,那么你应该从@ryanb,CanCan创建者那里检查这个提议,在那里他将这些能力分成几个不同的类然后覆盖current_ability

中的ApplicationController方法

How you can break up large Ability class in 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
...

等等其他文件。

答案 1 :(得分:2)

这里提到的部分解决方案真的很吸引人。我想提出一种替代方法来处理这个问题,我们覆盖application_controller中的current_ability方法,使其动态,具体取决于所使用的控制器。从那里我们可以指定在每个控制器中使用的能力。它可能看起来像这样:

./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继承以添加所需的逻辑。

答案 2 :(得分:-2)

您可以简单地将您的能力类转移到数据库并管理那里的所有权限并在检查current_user执行操作的能力之前获取。在将权限移动到db时不会花费太多时间。