leaning diary Rails

【Learning Daily21】Punditを使った認証システムに新しいPolicyを追加する

26/10/2023

【Learning Daily21】Punditを使った認証システムに新しいPolicyを追加する

 

今日はPunditに触れました。

 

最初は意味するところが分からず戸惑ったのですが、ReadMeを読んで、各変数の値をログで確認することで明確に理解することができました。

Pundit とは

Punditは、通常のRubyクラスとデザイン思考パターンを活用して、簡単に堅牢かつ拡張可能な認可システムを構築するためのヘルパーセットを提供するRubyGemです。

 

Punditは、policyクラスで認可のルールを設定します。

 

policyクラスはapp/policies配下のapplication.policyに定義します。

 

ログイン認証にオプションで様々な条件をつけていきたい場合は、同ディレクトリ内に、ApplicationPolicy を継承したファイルを作成していくと良いです。

policyクラスの前提

■モデル・クラスと同じ名前にただ「Policy」接尾語が付きます。

 

最初の引数はユーザーです。

コントローラでは、Pundit が current_user メソッドを呼び出してこの引数に送る内容を取得します。

 

第二引数には、認可をチェックしたいモデルオブジェクトを指定します。

ActiveRecordやActiveModelオブジェクトである必要はありません。

 

■Policyクラスは何らかのクエリメソッドを実装しています。通常、これは特定のコントローラアクションの名前に対応します。

 

以下は一例です。

 

class ApplicationPolicy
 #読み取り専用のゲッターメソッドを定義
 attr_reader :user, :record

 #第一引数はユーザーです。第2引数は認可をチェックしたいオブジェクトを指定します。
 def initialize(user, record)
 @user = user
 @record = record
 end

 def update?
 user.admin? || !record.published?
 end
 end

 

Punditは、たとえばPostクラスで呼ばれると、PostPolicyを探して適用する仕様になっています。

 

policyのファイル名を別途設定する場合は、policy_class: を指定します。

 

例えば、PostコントローラーでNextPositionPolicyの認可を利用する場合は、以下のようなコードになります。

 

authorize @post, policy_class: NextPostPolicy

 

理解に時間がかかった理由

スムーズに理解するために、ReadMeと変数をもっと早くみておけばよかったなぁと言うのが今日の反省です。

 

例えば、authorize @post の@post は、policy側ではrecordと認識されます。

 

その場合のuserは、current_userでした。

 

どのように定義するかで変わってきますのであくまで私のケースとはなりますが、意図した挙動にならないときは、早めに変数の中身を確認しておくと躓かずに解決方法がわかります。

 

これは今回に限ったことではないと感じたので、今後他のgemの利用でも心がけたいと思います。

 

Github varvet/pundit

 

-leaning diary, Rails