Ryan Bate の CanCan gem を使用して能力を定義していますが、いくつかの基本機能が失敗しています。Product モデルと Products コントローラーがあり、インデックス アクションは次のようになります。
def index
@req_host_w_port = request.host_with_port
@products = Product.accessible_by(current_ability, :index)
end
accessible_byメソッドで製品を取得しようとするとエラーが発生します。次のエラーが発生します。
Cannot determine SQL conditions or joins from block for :index Product(id: integer, secret: string, context_date: datetime, expiration_date: datetime, blurb: text, created_at: datetime, updated_at: datetime, owner_id: integer, product_type_id: integer, approved_at: datetime)
私の能力クラスは次のようになります。
can :index, Product do |product|
product && !!product.approved_at
end
これは非常に単純な例のように見えるので、これが失敗していることに驚いており、何か単純なことを見落としているのではないかと思います (つまり、コードを長時間見つめているなど)。
もう少し調べて、簡単なテストを実行しました。以下のコードを見ると、1 つの例は正常に動作し、1 つの例は実際にはまったく同じことを行うべきところで失敗しています。
# This works
can :index, Product, :approved_at => nil
# This fails
can :index, Product do |product|
product && product.approved_at.nil?
end
したがって、問題は CanCan がこれらのブロックを処理する方法にあるようです。私はライブラリを深く掘り下げて、エラーが発生した場所を見つけました-CanCanの能力クラス定義で:
def relevant_can_definitions_for_query(action, subject)
relevant_can_definitions(action, subject).each do |can_definition|
if can_definition.only_block?
raise Error, "Cannot determine SQL conditions or joins from block for #{action.inspect} #{subject.inspect}"
end
end
end
そこで、このonly_block?方法とは何かを調べてみました。このメソッドは、can 定義にブロックが含まれていても意味をなさない条件がない場合に true を返します。これは、ブロックの要点は、次の構文では複雑すぎる場合にブロック内の条件を定義することであるためです。
can :manage, [Account], :account_manager_id => user.id
この問題に関する洞察は素晴らしいでしょう!CanCan github ページにも問題を提出しましたが、ライブラリを捨てる必要があるかもしれないところまで来ています。ただし、多くの人が CanCan をうまく使用していることを理解しています。これは非常に基本的な機能であり、何か間違ったことをしているに違いないと思います。特に、3 日前に git リポジトリが更新され、Ryan Bates が README で Rails 3 のサポートについて言及しているためです。
ありがとう!