Rails::Initializer ロードパス系の処理を見る

Rails::Initializerまだまだ続くよ

processメソッドで呼ばれるメソッドで

  • set_load_path
  • require_frameworks
  • set_autoload_paths
  • add_plugin_load_paths
  • load_environment

名前からして全部ロード系ですから、一気に行きますよ。

set_load_path

def 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

def 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

# Set the paths from which Rails will automatically load source files, and
# 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

# Adds all load paths from plugins to the global set of load paths, so that
# 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

# Loads the environment specified by Configuration#environment_path, which
# 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

関連記事

  1. Rails::Initializer.runは2回(以上)実行されている?
  2. 毎日読むRails initializer.rb #02
  3. 毎日読むRails environment.rb その2
  4. Rails::Initializer.check_ruby_version()
  5. Mac版RadRailsでscript/consoleが通らない件
Posted in ruby, ruby on rails, 日記 at 3月 4th, 2008. Trackback URI: trackback

No Responses to “Rails::Initializer ロードパス系の処理を見る”

Leave a Reply