tapitapi’s blog

1日1杯タピオカ!エンジニア

【Ruby on Rails: cancancan】canの旅 (ソースコードリーディング)第六回

目指せ!ruby&railsマスター!

 

ということで、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::ControllerResourceSanitizer

  def 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_resource

   end
  end 

 end

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])

cancancan/controller_additions.rb at 6d0e62bf0c475964a0533608e7e7221be45de28c · CanCanCommunity/cancancan · GitHub

 

 

@options[:singleton]はsingletonの時trueを返すらしい、、

Pass +true+ if this is a singleton resource through a +has_one+ association.

 

cancancan/controller_additions.rb at 6d0e62bf0c475964a0533608e7e7221be45de28c · CanCanCommunity/cancancan · GitHub

 

Singleton パターン - Qiita

  

 

load_resource methodはこの「build_resource」「find_resource」が肝っぽいですね!

 

今日はここまでー!

次回はbuild_resource methodを扱っていきます。

 

おやすみなさいいいいぃぃぃ