Rails: action_policy gemの紹介|TechRacho by BPS株式会社

Railsアプリケーションで利用可能な認可gemであるaction_policyの機能を紹介します。
ここでは類似したパラダイムで構成されるpunditと比較しながら説明していきます。

palkan/action_policy - GitHub
varvet/pundit - GitHub

他にはcancancan gemも有名ではありますが、こちらとの比較は既存記事の「Authorization in Rails controllers: Pundit versus CanCan」などに譲ります。

CanCanCommunity/cancancan - GitHub

punditとaction_policy

punditとaction_policyの機能はかなり近しいです。action_policyがpunditを参考にしているため当然の話ではあります。
action_policy自身は「punditで必要とされていたHACKがaction_policyになった」と主張しており、これが両者の差異になります。

What about the existing solutions? — Action Policy: authorization framework for Ruby/Rails applications

以下、細かい話ですが例を二つご紹介します。

namespaceの推論

action_policyではPolicyのnamespaceを推論することができます。

Namespaces — Action Policy: authorization framework for Ruby/Rails applications

module Admin
  class UsersController 

一方でpundtiでは呼び出し時に明示的な指定が必要です。

Policy Namespacing — varvet/pundit: Minimal authorization through OO design and pure Ruby classes

authorize(post)                   # => will look for a PostPolicy
authorize([:admin, post])         # => will look for an Admin::PostPolicy
authorize([:foo, :bar, post])     # => will look for a Foo::Bar::PostPolicy

policy_scope(Post)                # => will look for a PostPolicy::Scope
policy_scope([:admin, Post])      # => will look for an Admin::PostPolicy::Scope
policy_scope([:foo, :bar, Post])  # => will look for a Foo::Bar::PostPolicy::Scope

認可対象名とPolicyクラス名の不一致の処理

例として、以下のように注文(Order)をキャンセルするためのコントローラーを作成し、このアクションをリクエストするボタンをViewで実装することにします。

class Orders::CancelsController 

punditで実装する場合、まず以下のようなPolicyクラスを作成します。

class Orders::CancelPolicy 

punditでは、このように認可対象とクラス名が一致していないPolicyについて、Viewから呼び出すためのインターフェースが若干弱いです。
通常であれば #policy というヘルパーメソッドを利用できます。



  

しかし、このメソッドを通じて Orders::CancelPolicy のロジックを呼び出すことができません。




  




  




  

単にPolicyを呼び出すだけであれば、 Orders::CancelPolicy.new とすれば可能です。


  

ただし、punditにはPolicyインスタンスのキャッシュという機能があり、 #policy メソッドを経由せずに作成されたインスタンスにはこのキャッシュが効きません。
キャッシュが効かないから致命的ということはないのですが、用意されたインターフェースを利用しないためにパフォーマンス上の恩恵を受けられず、HACKのような実装になってしまいます。


一方、action_policyにはAuthorization Contextという、その名の通り認可コンテキストを指定する機能が存在します。
Policyクラスを作成するときにこのコンテキストを指定します。

class Orders::CancelPolicy 

Viewからは allow_to? ヘルパーメソッドの with: オプションを指定することで、Policyクラスのロジックを呼び出すことができます。


  

これは素直な呼び出し方に見えますし、punditと違ってPolicyインスタンスのキャッシュも効きます
punditで微妙に手が届かない箇所をカバーする一例として紹介しました。


その他、punditとの差分内容についてはaction_policyの公式ドキュメントをご参照ください。

What about the existing solutions? — Action Policy: authorization framework for Ruby/Rails applications

個人的には、action_policyで不満足なことがないため、認可gemにはこちらを採用するようになりました。


元の記事を確認する

関連記事