3 月 04 2008
Rails::Initializer ロードパス系の処理を見る
Rails::Initializerまだまだ続くよ
processメソッドで呼ばれるメソッドで
- set_load_path
- require_frameworks
- set_autoload_paths
- add_plugin_load_paths
- load_environment
名前からして全部ロード系ですから、一気に行きますよ。
set_load_path
load_paths = configuration.load_paths + configuration.framework_paths
load_paths.reverse_each { |dir| $LOAD_PATH.unshift(dir) if File.directory?(dir) }
$LOAD_PATH.uniq!
end
configrationで設定したロードパスとフレームワークパスの配列を結合して、$LOAD_PATHにディレクトリかどうかのチェックと、ユニークのチェックをして追加しています。
require_frameworks
configuration.frameworks.each { |framework| require(framework.to_s) }
rescue LoadError => e
# re-raise because Mongrel would swallow it
raise e.to_s
end
Configration#frameworksで指定されているフレームワークを読み込みます。
読み込みに失敗した場合、Mongrelでは「飲み込まれる」らしいのでもう一度エラーをraiseしています。
set_autoload_paths
# the load_once paths.
def set_autoload_paths
Dependencies.load_paths = configuration.load_paths.uniq
Dependencies.load_once_paths = configuration.load_once_paths.uniq
extra = Dependencies.load_once_paths - Dependencies.load_paths
unless extra.empty?
abort <<-end_error
load_once_paths must be a subset of the load_paths.
Extra items in load_once_paths: #{extra * ','}
end_error
end
# Freeze the arrays so future modifications will fail rather than do nothing mysteriously
configuration.load_once_paths.freeze
end
いきなり登場したDependencies。名前からして「依存」を表すモジュールなんでしょう。
ドキュメントも特にありませんので、今のところ無視します。
configurationのロードパスと、一度だけロードするパスをDependenciesにコピーしています。 load_pathsにload_once_pathsに加えるべきパスがあった場合は強制終了。 configuration.load_once_pathsもfreezeで凍結しています。
add_plugin_load_paths
# code from plugins can be required (explicitly or automatically via Dependencies).
def add_plugin_load_paths
plugin_loader.add_plugin_load_paths
end
# 中略
def plugin_loader
@plugin_loader ||= configuration.plugin_loader.new(self)
end
読みにくくなってきたなぁ。
ちょっと割愛させてもらいますが、
configuration.plugin_loaderはPlugin::Loaderを指しています(デフォルトで)。
Plugin::Loaderがどこにあるのかは、ちょっとわからなかったです。
とにかくプラグインのパスをロードパスに追加していると・・。
load_environment
# is typically one of development, test, or production.
def load_environment
silence_warnings do
return if @environment_loaded
@environment_loaded = true
config = configuration
constants = self.class.constants
eval(IO.read(configuration.environment_path), binding, configuration.environment_path)
(self.class.constants - constants).each do |const|
Object.const_set(const, self.class.const_get(const))
end
end
end
なんかすげー書き方してますね・・。わかりづらすぎて憎しみすら覚えます。
指定されたenvironmentファイルを読むと。productionとかdevelopmentとかtestとかの例のアレを読み込む処理がここという事ですね。今日読む中では一番親しみ深い部分かもしれませんね、書き方以外は。
silence_warningsはrails apiで検索すると、ActiveSupportでKernelにたいして拡張されたメソッドだという事がわかります。 警告を出さずにブロックを実行するためのメソッドのようです。
self.class.constantsはトップオブジェクトが持つ定数を配列で返します。
eval式を使ってconfiguration.environment_pathの内容("#{root_path}/config/environments/#{environment}.rb")をRuby式として評価する前と後で、トップオブジェクトが持つ定数の差をeachで回してObjectに定数を代入している。 って、正直よくわかんないです。次回もうちっと踏み込んでみよう。
実際のソースにトレースを仕込んで挙動を確認したりしないと、もう無理だな・・。
参考
http://d.hatena.ne.jp/walf443/20060707/rails_initializer
http://rubyist.g.hatena.ne.jp/muscovyduck/20060528/p1
http://d.hatena.ne.jp/rubyco/20060311/constants