我正在编写一个Web应用程序,以从较大,完整的卡片集中选择随机列表。我有卡片型号和卡特型号。两种模型都有7个动作的完整恢复集(:index,:new,:show等)。 CardsetScontroller有一个额外的动作来创建随机集: :random.

# app/models/card_set.rb
class CardSet < ActiveRecord::Base
  belongs_to :creator, :class_name => "User"
  has_many :memberships
  has_many :cards, :through => :memberships

# app/models/card.rb
class Card < ActiveRecord::Base
  belongs_to :creator, :class_name => "User"
  has_many :memberships
  has_many :card_sets, :through => :memberships

我添加了为授权的身份验证和CANCAN设计的设计。我有具有“编辑”角色的用户。允许编辑创建新卡片。来宾用户(尚未登录的用户)只能使用 :index:show 动作。这些授权正在按设计工作。编辑当前可以同时使用 :random:new 没有任何问题的行动。如预期的那样,来宾用户无法。

# app/controllers/card_sets_controller.rb
class CardSetsController < ApplicationController
  before_filter :authenticate_user!, :except => [:show, :index]
  load_and_authorize_resource

我想允许来宾用户使用 :random 动作,但不是 :new 行动。换句话说,他们可以看到新的随机集,但不能保存它们。在 :random 动作的视图是从客人用户隐藏的。问题是,第一件事 :random 操作确实是构建卡片模型的新实例以填写视图。坎卡(Cancan)试图 load_and_authorize_resource 一张新卡片,它会抛出cancan ::访问型例外。因此,视图永远不会加载,并且为客人用户提供了“您需要在继续登录或注册”消息。

# app/controllers/card_sets_controllers.rb
def random
  @card_set = CardSet.new( :name => "New Set of 10", :set_type => "Set of 10" )

我意识到我可以告诉 load_and_authorize_resource 跳过 :random 通过通过 :except => :random 通话,但这只是感觉 “错误的” 由于某些原因。

是什么 “正确的” 这样做的方法?我应该在不实例化新卡片的情况下创建新的随机集吗?我应该继续添加例外吗?

更新

我没有上面包括我的能力课。我已将其更新为包括“:随机”操作,但它仍然没有正常工作。

class Ability
  include CanCan::Ability

  def initialize( user )
    user ||= User.new # User hasn't logged in

    if user.admin?
      can :manage, :all if user.admin?
    else
      # All users, including guests:
      can :read, [Card, CardSet]
      can :random, CardSet

      # All users, except guests:
      can :create, [Card, CardSet] unless user.role.nil?
      can :update, [Card, CardSet] do |c|         
        c.try( :creator ) == user || user.editor?
      end

      if user.editor?
        can [:create, :update], [Card, CardSet]
      end
    end
  end
end
有帮助吗?

解决方案

我发现我的问题。 Cancan根本不是问题!我的卡特控制器中的以下行是抛出例外,并将我的访客(未登录)用户重定向到登录页面:

before_filter :authenticate_user!, :except => [:show, :index]

我将其更改为阅读:

before_filter :authenticate_user!, :except => [:show, :index, :random]

现在,代码按预期工作:访客用户可以查看创建的新随机集,但除非它们首先登录,否则无法“保存”它们。

因此,我真正的问题是设计(或实际上是我的设计配置),而不是与Cancan一起。

其他提示

好吧,正确的事情是使用CANCAN能力类来定义正确的授权规则。

在能力

  def initialize(user)
#everyone
    can [:read, :random], [CardSet]
#everyone who is editor
    if user.editor?
      can [:new, :create], [CardSet]

ETC

问题是,第一件事:随机操作确实是构建卡片模型的新实例以填写视图。当Cancan尝试load_and_authorize_resource一张新卡片时,它会抛出cancan :: AccessDened Exception。

尽管Cancan授权控制器操作,但在随机操作(IE Cardset.new)中构建新实例不在Cancan的范围内。您可能会出现错误,因为您没有能力中定义的规则。RB用于随机操作。我上面的示例应该解决您的问题

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top