はじめに
cancancanというgemでは、authorize_resourceというメソッドが用意されています。
authorize_resourceは、以下のように使うと、Controller名から対象のリソースを特定してくれる機能があります。
その特定の仕組みが気になったので、今回はそのコードを対象に読んでみました。
class BooksController < ApplicationController
authorize_resource # この場合、Bookに対する権限をチェックしてくれます。
# ...略
end
コードリーディング
authorize_resourceメソッドは以下に定義されていました。
@controller.authorize!で以前も記事にしたauthorize!メソッドが使われています。
今回はcontrollerから第二引数のresource_class_with_parentのソースコードを追っていこうと思います。
def authorize_resource
return if skip?(:authorize)
@controller.authorize!(authorization_action, resource_instance || resource_class_with_parent)
end
parent_resourceはthroughを使った際に関連しますが、今回は省略します。
resource_classの定義を見ていきます。
def resource_class_with_parent
parent_resource ? { parent_resource => resource_class } : resource_class
end
@optionには、load_resourceに渡しているオプションの情報が格納されています。
今回はオプションを渡していないので、when nilに進み、namespaced_nameを返します。
def resource_class
case @options[:class]
when false
# ...略
when nil
namespaced_name.to_s.camelize.constantize
when # ...略
else
# ...略
end
end
namespaced_nameではnamespaceとnameが使われています。
namespaceとnameによって名前空間も含め、コントローラからリソースとなるモデルを特定していました。
def name_from_controller
@params[:controller].split('/').last.singularize
end
def namespaced_name
[namespace, name].join('/').singularize.camelize.safe_constantize || name
end
def name
@name || name_from_controller
end
def namespace
@params[:controller].split('/')[0..-2]
end
さいごに
authorized_resourceでどうやってリソースを特定しているんだろうと思いましたが、調べてみたらRailsの仕組みをかなり活用していることがわかっておもしろかったです。