権限管理Gem「Pundit」の権限判定処理を直接呼び出したい

こんにちは!kossyです!




今回は権限管理Gem「Pundit」の権限判定処理を直接呼び出したい時の書き方について、ブログに残してみたいと思います。




環境

Ruby 2.6.6
Rails 6.0.3
MacOS Catalina




実装

通常、PunditはController内でauthorizeメソッドと共に呼び出すことが多いと思いますが、Controller以外の場所で直接呼び出したい場合はどうすればいいでしょうか。

結論、以下のように書けばOKです。

# 既にUserPolicyが作成されていて、show?メソッドが定義されているのを前提としています。

Pundit.policy!(current_user, User).show?

policy!メソッドの第一引数に現在ログイン中のユーザーを、第二引数にPolicyを実行したいclass名を渡し、そのPolicyクラス(上記の例だとUserPolicy)に定義された権限判定のメソッドを呼び出せばOKです。

policy!メソッドの中身を覗いてみる

ついでにGem内の実装を確認してみましょう。

github.com

    def policy!
      policy or raise NotDefinedError, "unable to find policy `#{find(object)}` for `#{object.inspect}`"
    end

policyメソッドも見る必要がありそうなので、確認してみます。

    def policy
      klass = find(object)
      klass.is_a?(String) ? klass.safe_constantize : klass
    end

実行するPolicyクラスを見つけに行く処理ですね。

Policy!メソッドの方は、引数に渡したPolicyが見つからない場合は、例外を返すようになっています。

policyとpolicy!の使い分けは、引数に渡したPolicyが見つからない場合に例外が欲しいかどうかで分ければよさそうです。




勉強になりました。