Punditにコミットした
結果的には破壊的変更をしてしまったのでPR送った経緯を書いておこうと思う。 もちろんこのままリリースされるかはわからないけど。
ちなみにPunditは以下のように明瞭な形でリソースに対しての行動に制約を設定できるようになるGemだ。
class PostPolicy attr_reader :user, :post def initialize(user, post) @user = user @post = post end def update? user.admin? or not post.published? end end # in controller def update @post = authorize Post.find(params[:id]) if @post.update(post_params) redirect_to @post else render :edit end end
書きやすく読みやすいコードが書けて良いGemだと思う。
PRを立てた経緯
業務でPunditを利用させてもらっていて、ちょっと面倒なところがあった。
https://github.com/varvet/pundit#policy-namespacing にもあるがこのようなコードだ。
module Admin class PostPolicy ~~ end end class AdminController < ApplicationController def authorize(record, query = nil) super([:admin, record], query) end end class Admin::PostController < AdminController def show post = Post.find(params[:id]) authorize(post) end end
「同じリソースに対してpolicy*1を名前空間で分けて複数設定する」というのはよく行うのだけれど、Punditは上記のように名前空間を配列で渡すとpolicyを推測して読み込んでくれる。
がしかし、この方法をつかうとせっかくクールなこの書き方が使えなくなってしまう。
def show @user = authorize User.find(params[:id]) end
authorize
は渡された引数をそのまま返すので上記のように綺麗にかけるのだが、名前空間を推測させるために配列を渡すとそのまま配列が帰ってきてしまうのである。
仕方がないので業務では
class AdminController < ApplicationController def authorize(record, query = nil) super([:admin, record], query) record end end
としてrecordが帰ってくるようにした。*2
recordが帰ってくるのが望ましいだろう、ということでせっかくのOSSだし修正の提案をしたのがPRを立てるまでの経緯だ。
PR立てた後
マージされるまでメンテナーの方に丁寧なレビューをもらい感謝しかない。こういってはなんだが自分としては無料で自分のコードみてもらって良いことしかなかった。
「OSSはやることが多くて大変」という言葉をOSSパッチ会でkoicさんもおっしゃっていたが、本当に尊敬できる方たちだと思う。
Punditという素晴らしいGemをメンテしていただきありがとうございます。READMEの更新を忘れて後ですごすごPR立ててすいません
最近Elixirが楽しかったがRubyもやっぱり面白い。