我正在编写一个网络应用程序来从更大、完整的卡片组中随机选择卡片列表。我有一个 Card 模型和一个 CardSet 模型。两种模型都有完整的 RESTful 集 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。我有具有“编辑”角色的用户。允许编辑器创建新的 CardSet。来宾用户(未登录的用户)只能使用: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
操作所做的第一件事是构建 CardSet 模型的新实例来填充视图。当 cancan 尝试load_and_authorize_resource
一个新的 CardSet 时,它会抛出一个 CanCan::AccessDenied 异常。因此,视图永远不会加载,并且会为来宾用户提供“您需要先登录或注册才能继续”消息。
# 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
,这只是感觉“错误” 。
这样做的“正确”方法是什么?我应该在不实例化新 CardSet 的情况下创建新的随机集吗?我应该继续添加例外吗?
更新
我没有在上面包括我的能力课程。我已对其进行了更新以包含 ':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