3

初めての Ruby on Rails アプリに cancan を取り込もうとしています。

始めるのに問題があります...それは確かに基本的なものです。

私のアプリケーションにはプロジェクトのリストがあり、ユーザーはそれらのいくつかを表示する権限を持っている場合と持っていない場合があります。

これを ProjectsController に追加しました:

class ProjectsController < ApplicationController
  load_and_authorize_resource

私の初期化メソッドは次のようになります。

  def initialize(user)
    user ||= User.new # guest user
    puts "********  Evaluating cancan permissions for: " + user.inspect
    can :read, Project do |project|
      puts "********  Evaluating project permissions for: " + project.inspect
      # project.try(project_users).any?{|project_user| project_user.user == user} 
      1 == 1  #POC test!
    end
  end

これがあると、プロジェクトのインデックス ページが表示されますが、プロジェクトが一覧表示されません。

私がここに持っている2つの質問:

  1. すべてのプロジェクトに対して true が返されるため、すべてのプロジェクトが表示されるべきではありませんか?
  2. 2 番目の puts ステートメントは Rails サーバー コンソールに書き込まれませんが、最初のステートメントは書き込まれます。何故ですか???

初期化メソッドを次のように変更すると:

  def initialize(user)
    user ||= User.new # guest user
    puts "********  Evaluating cancan permissions for: " + user.inspect
    can :read, Project
  end

... 期待どおりにすべてのプロジェクトが表示されます

can :read, Project の行を削除すると、プロジェクトのインデックス ページにアクセスしようとしてセキュリティ例外が発生します。これも期待どおりです。

4

1 に答える 1

0

:read 機能に渡されるブロックは、プロジェクトのインスタンスが利用可能な場合にのみ評価されます ( @project)。index アクションについて話しているため、コレクションのみが使用可能です ( @projects)。これは、2 番目の puts ステートメントが表示されない理由を説明しています。インデックス アクションを制限するには、条件のハッシュをcanメソッドに渡すか、(ブロックに加えて) スコープを使用する必要があります。この情報はすべて、Github の CanCan wiki で明確に概説されています。

したがって、puts問題は説明可能です。意味をなさないのは、プロジェクトが表示されていないことです。index アクションを評価するとき、CanCan は実際にはデフォルトでブロックを完全に無視します。これは、あなたの能力がcan :read, Projectとにかく(最初の例であっても)インデックスアクションにとって本質的であることを意味します。

単純なスコープを追加してみて、それが機能するかどうかを確認していただければ幸いです。試す:

can :read, Project, Project.scoped do |project|
  true
end

次に、index アクションで何が起こるかを確認します。

編集:

インデックスでプロジェクトを確認できるようになったことを考えると、ブロックだけでなくスコープもアビリティに渡す必要があるようです。Ryan が index アクションでブロックが評価されない理由を説明しているこの Github の問題を読んでください。

ブロックは、オブジェクトの属性に基づいて能力を定義するためにのみ使用することを意図しています。[...] オブジェクトが使用可能な場合にのみブロックが実行されるため、ブロックを使用する必要があるのはこれだけです。他のすべての条件は、ブロックの外で定義する必要があります。

あなたの能力が条件のハッシュに対して複雑すぎない場合は、代わりにそれを使用する必要があることに注意してください. 条件のハッシュについては、Github のこの CanCan wiki ページで説明されています。スコープが必要な場合は、スコープとブロックを渡す必要があります。あなたが上記の能力を持っているとしましょう。

  1. index アクションでは、Project オブジェクト ( ) が使用できないため、CanCan はブロックを無視し@projectます。代わりに、指定されたスコープ内のプロジェクトを返しますProject.scoped(この場合はすべてのプロジェクトになります)。
  2. show アクションで@projectは が使用可能であるため、CanCan はブロックを評価し、ブロックが true と評価された場合にアクションを許可します。

したがって、両方を渡す必要があるのは、CanCan が index アクションと show アクションの両方を処理できるようにするためです。ほとんどの場合、ブロックはスコープと同じものを定義します。ブロックのみが Ruby で記述され、スコープは Rails の ActiveRecord 構文で記述されます。詳細については、こちらを参照してください:ブロックを使用したアビリティの定義.

于 2013-03-29T14:05:16.273 に答える