0

CanCan を使用して、サイトのコメントの表示を制限しようとしています。私のコメントモデルでは、列挙型が定義されています:

  enum access_right: {nobody: 0, somebody: 1, everyone: 2}

これが私の現在のability.rbファイルの抜粋です:

class Ability
    include CanCan::Ability

    def initialize(user, session={})
        user ||= User.new # guest user (not logged in)
        # Comments
        can [:create, :read, :update, :destroy], Comment, person_id: person.id
        can [:read], Comment, access_right: [:everyone, Comment.access_rights[:everyone]]
        ...
    end
end

最初は次のものを使用していました:

can [:read], Comment, access_right: 2

しかし、これはレコードを取得するときに機能しますが:

Comment.accessible_by(...)

次のようなオブジェクトに対してアクセス許可をチェックする場合は機能しません。

can? :read, @a_comment

@a_comment.access_right == "全員" (2 ではない)

オンラインで調べたところ、CanCanCommunity issue 102が見つかりました。次のように「everyone」を直接使用するため、提案されたソリューションは私にとってはうまくいきませんでした。

can [:read], Comment, access_right: ["everyone", Comment.access_rights[:everyone]]

間違った結果になります。レコードをフェッチするときの背後にある SQL クエリは次のようになります。

SELECT `comments`.* FROM `comments`  WHERE `comments`.`access_right` IN (0,2))

この場合、「everyone」は整数 (0) にキャストされているようです。

その後、シンボル (:everyone) のおかげで、現在のアビリティ ファイルである回避策を見つけました。しかし、缶を使用すると、物事はもう機能しませんか?:read, @a_comment (accessible_by を使用すると、SQL は正しくなります)

この問題を修正する方法を知っている人はいますか?

レコードのフェッチ中と缶の両方で検証できる列挙型に基づいて能力を定義する方法は?

ありがとうございました!

編集: このCanCanCommunity issue 65に関連している可能性がありますが、機能させることはできません。

4

1 に答える 1

0

CanCan ブロック構文で実現できます。

# Please note this is an Array of Strings, not Symbols
allowed_access_rights = %w[everyone] 

can :read, Comment, ["access_right IN (?)", Comment.access_rights.values_at(allowed_access_rights)] do |comment|
  comment.access_right.in? allowed_access_rights
end

例のように、未加工の SQL 条件を使用する代わりに、モデルにスコープを定義してここに渡すのは魅力的ですが、

can :read, Comment, Comment.with_access_right(allowed_access_rights) do |comment| … end

柔軟性がはるかに低いため、実際にはお勧めできません。 CanCan docsを参照してください。

于 2015-01-19T22:54:05.290 に答える