require_dependencyってなんなんだろ。しょっちゅうrailsソース内ででてくるけど。ということで調べてみた。
activesupport/lib/active_support/dependencies.rbの
Object.send(:define_method, require_dependency) { |file_name| Dependencies.depend_on(file_name) }
define_methodで定義してる。最初 'def
require_dependency'
で検索したけどひっかからなくてここにたどり着くまでそこそこ時間がかかった、、、。
requireとの違い
require_dependencyで呼び出しているメソッド、depend_onは
<code> def depend_on(file_name, swallow_load_errors = false)
unless loaded.include?(file_name)
loaded << file_name
begin
require_or_load(file_name)
rescue LoadError
raise unless swallow_load_errors
end
end
end
</code>
同じ引数で呼び出されていなければrequire_or_loadメソッドを実行する。んでrequire_or_loadメソッドは
<code> def require_or_load(file_name)
file_name = "#{file_name}.rb" unless ! load? || file_name[-3..-1] == '.rb'
load? ? load(file_name) : require(file_name)
end
</code>
1行目で.rbだったり拡張子無しだったりするときの処理を。つーか解りにくいよ…。
<code> file_name = "#{file_name}.rb" unless ( (! load?) || file_name[-3..-1] == '.rb')
</code>
load?がtrueじゃない、かつファイル拡張子が.rbじゃ無いならfilenameは"#{file_name}.rb"になる、か。ここはさして重要じゃなくて次の
<code> load? ? load(file_name) : require(file_name)
</code>
でload?メソッドがtrueならloadメソッドで呼び出し、そうじゃなかったらrequireメソッドで呼び出しを行う。んでloadメソッドは
<code> @@mechanism = :load
mattr_accessor :mechanism
def load?
mechanism == :load
end
</code>
と定義されているため、何にも変更しなきゃrequire_dependencyを使うとloadメソッドで読み込まれると。デフォルトのgeneratorで生成した場合、RAILS_ROOT/config/environments/development.rbには
<code>Dependencies.mechanism = :load
</code>
RAILS_ROOT/config/environments/production.rbには
<code>Dependencies.mechanism = :require
</code>
と記述されてるのでproductionだとloadじゃなくてrequireされる。
で、んじゃrailsにおけるloadとrequireの大きな違いって何って事ってになるけど、fastcgiやwebrickでrails使ってる場合はloadでライブラリをロードしたときはもう一度無条件ロードされるため、ライブラリソースに変更があった場合はその変更が反映される。
requireの場合はすでに読み込んであったら読み込まない。通常のcgiで使ってる場合にはほとんど変わりなし。
だからdevelopmentではloadで、productionではrequireになってるんだね。自作ライブラリを作りったり修正したりしつつrailsの開発を進める場合はrequire_dependencyで読み込んでおくといいよ、と。