【Rails】権限管理のgem「pundit」を使ってみたときのまとめ
目的
punditというgemを使う際に「Rubyist Magazine - 権限管理のgem、Punditの紹介」を参考に作ったときのまとめ。
railsにapp/policies
ディレクトリって何を入れるのかというところを前回調べたのですが、代表的なものとしてpundit
というgemを使うと出て来るというのが代表的な例なようなので、使ってみました。
【Rails】policiesディレクトリの使い方 - ITの勉強をいろいろやってみたブログ
るびまを参考にして作ったときに考えていたこと等をまとめてみます。
まとめ
ApplicationPolicyのサブクラスの初期化時には、recordではなくclassを渡す
rails g pundit:install
を実行すると、app/policies/application_policy.rb
が作られるのだが、初期実装は以下のようになっている。
class ApplicationPolicy # ... def initialize(user, record) @user = user @record = record end # ... end
これだと、レコードを渡すことで「自分のレコードは更新できる。他の人のレコードは閲覧だけ。」みたいなレコード単位の権限をつけられる。
それはそれで便利なのだけど、社内用の管理画面等はレコード単位ではなくクラス・モデル単位での権限がついていれば十分。なので、以下のようにクラスを受け付ける想定にしておいて、その他も適宜書き換える。(モンキーパッチを当てる必要はなし)
class ApplicationPolicy # ... def initialize(user, klass) @user = user @klass = klass end # ... end
ApplicationController
には以下のようなメソッドを準備しておく。
class ApplicationController < ActionController::Base # ... def pundit_auth authorize controller_name.classify.constantize end end
UsersController
でbefore_action
を呼ぶ
class UsersController < ApplicationController before_action :pundit_auth # ... end
すっきり。
cancancan vs punditはRSpec vs minitestと似ている気がする
cancancanはAbility
というクラスを定義して、その中にDSLをわーっと書いて権限設定を定義します。
それに対しpunditはピュアなObjectを継承したpureなRubyのクラスで定義し、コントローラで呼ぶためのメソッドを提供しているだけです。
このような観点の比較はRSpec vs minitestのときの議論と似ているかなと思っています。
MinitestとRSpec、FixturesとFactoryGirlの良いところ悪いところをコードを書いて比較してみた - give IT a try
RSpec vs minitestのときはテストコードの話なのですが、権限は実際のアプリケーションの設計に関わってくる所なので、妥協したりプラグインに引っ張られた設計になるのは避けたいところです。
複雑な仕様がある場合にはcancancanにモンッキーパッチをあてる等して使うより、自由に書けるpunditを使っておくのも悪くない選択かなと思いました。
TODO
- cancancanで同じことをやる
- 認証はdeviceを使ってやったが、自前で実装してみる