次のモデルの Rails アプリがあります。
class User < ActiveRecord::Base
has_many :administrations
has_many :calendars, through: :administrations
end
class Calendar < ActiveRecord::Base
has_many :administrations
has_many :users, through: :administrations
end
class Administration < ActiveRecord::Base
belongs_to :user
belongs_to :calendar
end
与えられた に対して、にcalendar
は結合モデルで定義されている があります。user
role
administration
Owner
カレンダーごとに、ユーザーは、Editor
またはの 3 つの役割のうちの 1 つだけを持つことができますViewer
。
これらのロールは現在、ディクショナリまたは定数に格納されておらず、さまざまな方法で文字列 ("Ower"、"Editor"、"Viewer") として管理にのみ割り当てられます。
モデルの認証User
はDeviseを通じて処理され、current_user
メソッドは機能しています。
ログインしたユーザーのみがアプリ内リソースにアクセスできるようにするために、コントローラーとコントローラーにbefore_action :authenticate_user!
メソッドを既に追加しています。calendars
administrations
ここで、役割ベースの承認システムを実装する必要があるため、CanCanCan
gem をインストールしました。
これが私が達成したいことです:
- すべての (ログインしている)
user
は、新しい を作成できますcalendar
。 - a
user
が a の であるowner
場合、自分の を含め、this に属するすべての およびをcalendar
使用できます。manage
calendar
administration
calendar
administration
- ユーザーが
editor
の場合、このカレンダーを削除して、自分の を破棄calendar
できます。read
update
administration
- a
user
がviewer
a の場合、calendar
彼はread
これを行うことができcalendar
、destroy
彼のadministration
.
上記を実装するために、次のability.rb
ファイルを作成しました。
class Ability
include CanCan::Ability
def initialize(user, calendar)
user ||= User.new
calendar = Calendar.find(params[:id])
user can :create, :calendar
if user.role?(:owner)
can :manage, :calendar, :user_id => user.id
can :manage, :administration, :user_id => user.id
can :manage, :administration, :calendar_id => calendar.id
elsif user.role?(:editor)
can [:read, :update], :calendar, :user_id => user.id
can :destroy, :administration, :user_id => user.id
elsif user.role?(:viewer)
can [:read], :calendar, :user_id => user.id
can :destroy, :administration, :user_id => user.id
end
end
end
私は Rails についてあまり実験したことがなく、初めて使用するCanCanCan
ので、自分のコードにあまり自信がなく、改善のための検証またはアドバイスが必要です。
それで、このコードは機能し、必要なものを達成できるでしょうか?
更新:現在のコードでは、ユーザーとしてログインし、別のユーザーのカレンダーの calendars#show ページにアクセスすると、実際にカレンダーにアクセスできますが、アクセスしてはいけません。
したがって、明らかに、私のコードは機能していません。
私が間違っていることについて何か考えはありますか?
更新 2 :特定の に対して s がアクションを実行できるようにする:model
代わりにを使用していたため、コードにエラーがあると考えました。Model
user
model
ただし、コードはまだ機能していません。
ここで何が間違っている可能性がありますか?
更新 3 : ユーザーのロールが所有者に設定されているかどうかを確認するために使用するという事実によって問題が発生する可能性がありif user.role?(:owner)
ますが、データベースではロールは実際には「所有者」(文字列として) として定義されていますか?
更新 4: いくつかの調査を続けたところ、2 つの間違いを犯したことに気付きました。
およびコントローラーに追加
load_and_authorize_resource
していませんでした。calendars
administrations
メソッドで 1 つではなく、2 つの属性 2 つのパラメーター — <code>initialize(user, calendar) — を定義しました
initialize
。
そのため、次のように両方のコントローラーと、ability.rb ファイルを更新しました。
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
if user.role?(:owner)
can :manage, Calendar, :user_id => user.id
can :manage, Administration, :user_id => user.id
can :manage, Administration, :calendar_id => calendar.id
elsif user.role?(:editor)
can [:read, :update], Calendar, :user_id => user.id
can :destroy, Administration, :user_id => user.id
elsif user.role?(:viewer)
can [:read], Calendar, :user_id => user.id
can :destroy, Administration, :user_id => user.id
end
end
end
に属していないカレンダーにアクセスしようとするとcurrent_user
、次のエラーが表示されます。
NoMethodError in CalendarsController#show
undefined method `role?' for #<User:0x007fd003dff860>
def initialize(user)
user ||= User.new
if user.role?(:owner)
can :manage, Calendar, :user_id => user.id
can :manage, Administration, :user_id => user.id
can :manage, Administration, :calendar_id => calendar.id
どうすればこれを修正できますか?