3

次のモデルの 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は結合モデルで定義されている があります。userroleadministration

Ownerカレンダーごとに、ユーザーは、Editorまたはの 3 つの役割のうちの 1 つだけを持つことができますViewer

これらのロールは現在、ディクショナリまたは定数に格納されておらず、さまざまな方法で文字列 ("Ower"、"Editor"、"Viewer") として管理にのみ割り当てられます。

モデルの認証UserはDeviseを通じて処理され、current_userメソッドは機能しています。

ログインしたユーザーのみがアプリ内リソースにアクセスできるようにするために、コントローラーとコントローラーにbefore_action :authenticate_user!メソッドを既に追加しています。calendarsadministrations

ここで、役割ベースの承認システムを実装する必要があるため、CanCanCangem をインストールしました。

これが私が達成したいことです:

  • すべての (ログインしている)userは、新しい を作成できますcalendar
  • auserが a の であるowner場合、自分の を含め、this に属するすべての およびをcalendar使用できます。managecalendaradministrationcalendaradministration
  • ユーザーがeditorの場合、このカレンダーを削除して、自分の を破棄calendarできます。readupdateadministration
  • auserviewera の場合、calendar彼はreadこれを行うことができcalendardestroy彼の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代わりにを使用していたため、コードにエラーがあると考えました。Modelusermodel

ただし、コードはまだ機能していません。

ここで何が間違っている可能性がありますか?

更新 3 : ユーザーのロールが所有者に設定されているかどうかを確認するために使用するという事実によって問題が発生する可能性がありif user.role?(:owner)ますが、データベースではロールは実際には「所有者」(文字列として) として定義されていますか?

更新 4: いくつかの調査を続けたところ、2 つの間違いを犯したことに気付きました。

  1. およびコントローラーに追加load_and_authorize_resourceしていませんでした。calendarsadministrations

  2. メソッドで 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

どうすればこれを修正できますか?

4

1 に答える 1

1

role?User モデルにはそのような方法はありません。Cancancan のドキュメントは、そのようなメソッドが例に存在すると想定しているため、誤りがあります。

これを修正するには、代わりに次のことを行う必要があります。

if user.role == 'Owner'
  ...
elsif user.role == 'Editor'
  ...
elsif user.role == 'Viewer'
  ...
于 2015-09-22T20:11:31.050 に答える