【Ruby on Rails: cancancan】canの旅 (ソースコードリーディング)第六回
ということで、cancancanのソースコードリーディング第五回はじめます。
前回まではコチラ
前回はControllerResourceクラスのadd_before_actionの内部まで見ていきました!
今回ControllerResourceLoader moduleのload_resource methodを扱っていきます!
load_resource が何をしてくれるかは、下記がわかりやすいと思います!
https://qiita.com/umanoda/items/679419ce30d1996628ed#load_resource
とにかく、勝手に@user=find(params[:id])とかでインスタンス定数を作ってくれる!便利!
require_relative 'controller_resource_finder.rb'
require_relative 'controller_resource_name_finder.rb'
require_relative 'controller_resource_builder.rb'
require_relative 'controller_resource_sanitizer.rb'
module CanCan
module ControllerResourceLoader
include CanCan::ControllerResourceNameFinder
include CanCan::ControllerResourceFinder
include CanCan::ControllerResourceBuilder
include CanCan::ControllerResourceSanitizerdef load_resource
return if skip?(:load)if load_instance?
self.resource_instance ||= load_resource_instance
elsif load_collection?
self.collection_instance ||= load_collection
end
end
protected
def new_actions
%i[new create] + Array(@options[:new])#[:new, :create] と言う配列にハッシュ@options[:new]を配列にしたものを足す
end
def load_collection
resource_base.accessible_by(current_ability, authorization_action)
end
def load_resource_instance
if !parent? && new_actions.include?(@params[:action].to_sym)
build_resource
elsif id_param || @options[:singleton]
find_resourceend
endend
end
require_relativeで、まず外部ファイルを読み込んでいます。requireはrailsのrootからのパスを書かないといけないのですが、require_relativeでは、現在のファイルからの相対パスでOK!
その後、includeで他のmoduleを使える状態にします!
*return if skip?(:load)
skip?(:load)がtrue(実際はfalse or nil以外の戻り値。文字列や数字などでも可能)なら、return して、load_resource methodから抜けます。
skip? methodはおそらくincludeしたmoduleのどれかに定義されているけど、、、めんどくさいのでスキップ!(skip method だけにね、、、)
*if load_instance? elsif load_collection? end
おそらくincludeしたmoduleのどれかに定義されているけど、、、めんどくさいのでスキップ!
*self.resource_instance ||= load_resource_instance
self.resource_instanceに何も入っていないと、load_resource_instanceの値が入ります。
load_resource_instanceは、parentがfalseかつ、new_actionsに@params[:action]をシンボルにしたものが入っていれば、build_resource が呼ばれます。
def load_resource_instance
if !parent? && new_actions.include?(@params[:action].to_sym)
build_resource
elsif id_param || @options[:singleton]
find_resource
end
end
parent?は:parentを見てるっぽい
(下記のような使い方。コントローラの名前とは違うモデルのリソースをloadしたくて、さらにそのモデルが、コントローラのモデルの親でもない時。)
load_and_authorize_resource :post, :parent => false
https://github.com/CanCanCommunity/cancancan/wiki/Authorizing-controller-actions#custom-class
new_actions.include?(@params[:action].to_sym) だけども、
rails では必ずコントローラで、params[:action]とparams[:controller]を受け取る!
Action Controller の概要 - Railsガイド
つまり、コントローラのアクションがnew or create のときはbuild_resourceが基本的に呼ばれるのでは?
id_param || @options[:singleton] の条件の時、find_resourceが呼ばれます。
下記によると、id_paramはこんな感じの使い方。なんで@options[:id_param] じゃないのかな、、
load_resource :id_param => :url # will use find(params[:url])
@options[:singleton]はsingletonの時trueを返すらしい、、
Pass +true+ if this is a singleton resource through a +has_one+ association.
load_resource methodはこの「build_resource」「find_resource」が肝っぽいですね!
今日はここまでー!
次回はbuild_resource methodを扱っていきます。
おやすみなさいいいいぃぃぃ