私は、より大きな完全なカード セットからカードのランダム リストを選択する Web アプリを作成しています。Card モデルと CardSet モデルがあります。どちらのモデルにも、7 つのアクション (:index、:new、:show など) の完全な RESTful セットがあります。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
認証用の Devise と承認用の 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 モデルの新しいインスタンスを作成してビューを埋めることです。cancanload_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