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
Rails::Configuration.load_paths と Rails::Configuration.framework_paths を、Ruby組み込み変数 $LOAD_PATH に追加しています。
Configuration.load_paths, はConfigurationのインスタンス変数で、 Configuration初期化時にデフォルトにセットされます。
def initialize
~~ 略 ~~
self.load_paths = default_load_paths
~~ 略 ~~
end
def default_load_paths
paths = []
# Add the old mock paths only if the directories exists
paths.concat(Dir["#{root_path}/test/mocks/#{environment}"]) if File.exists?("#{root_path}/test/mocks/#{environment}")
# Add the app's controller directory
paths.concat(Dir["#{root_path}/app/controllers/"])
# Followed by the standard includes.
paths.concat %w(
app
app/metal
app/models
app/controllers
app/helpers
app/services
lib
vendor
).map { |dir| "#{root_path}/#{dir}" }.select { |dir| File.directory?(dir) }
paths.concat builtin_directories
end
def builtin_directories
# Include builtins only in the development environment.
(environment == 'development') ? Dir["#{RAILTIES_PATH}/builtin/*/"] : []
end
ここで、アプリの app/ 以下がロードパスに追加されています。
# app/controllers が 重複して追加されてる??
また、development環境の場合は、最後に rails/builtin がパスに追加されます。
processメソッドにブロックが与えられた場合(config/environment.rbから呼ばれたとき)は、load_path が environment.rb で指定した値で上書きされているはずです。
Configuration.framework_paths のほうは、変数ではなくメソッドになっています。
def framework_paths
paths = %w(railties railties/lib activesupport/lib)
paths << 'actionpack/lib' if frameworks.include?(:action_controller) || frameworks.include?(:action_view)
[:active_record, :action_mailer, :active_resource, :action_web_service].each do |framework|
paths << "#{framework.to_s.gsub('_', '')}/lib" if frameworks.include?(framework)
end
paths.map { |dir| "#{framework_root_path}/#{dir}" }.select { |dir| File.directory?(dir) }
end
ここで railties, activesupport, actionpack, activerecord, actionmailer, activeresource, actionwebservice と、すべてのRailsフレームワークがロードパスに追加されます。frameworks変数でロードするモジュールをフィルタしているので、そのデフォルト値をみてみると
def default_frameworks
[ :active_record, :action_controller, :action_view, :action_mailer, :active_resource ]
end
となっています。
なお、environment.rb で config.frameworks を編集して、
config.frameworks -= [ :active_record ]
たとえばこのように activerecordモジュールを frameworks から除いても、activerecord がロードパスから外れることはありません。config/boot.rb 内で、一度デフォルトのConfigurationで set_load_path が実行され、そのときにロードパスに追加されるためです。
(ただし、ロードはされません。当然か ^^;)
↑の設定で script/console を実行すると、
>> p ActiveRecord # 例外発生
NameError: uninitialized constant ActiveRecord
from /usr/lib/ruby/ruby-1.9.1/lib/ruby/gems/1.9.1/gems/activesupport-2.3.3/lib/active_support/dependencies.rb:443:in `load_missing_constant'
from /usr/lib/ruby/ruby-1.9.1/lib/ruby/gems/1.9.1/gems/activesupport-2.3.3/lib/active_support/dependencies.rb:80:in `const_missing_with_dependencies'
from /usr/lib/ruby/ruby-1.9.1/lib/ruby/gems/1.9.1/gems/activesupport-2.3.3/lib/active_support/dependencies.rb:92:in `const_missing'
from (irb):1
from /usr/lib/ruby/ruby-1.9.1/bin/irb:12:in `<main>'
>> require 'active_record' # activerecord をロード(成功)
=> ["ActiveRecord"]
>> p ActiveRecord # 今度は見つかる
ActiveRecord
=> ActiveRecord
という状態。
set_load_path で $LOAD_PATH にパスを追加するときのコードを見ると、Railsでのパスの検索順がみえてきます。
load_paths = configuration.load_paths + configuration.framework_paths
load_paths.reverse_each { |dir| $LOAD_PATH.unshift(dir) if File.directory?(dir) }
reverse して $LOAD_PATH に unshift しているので、最初に検索されるのはアプリの app ディレクトリ(のはず)。
[Rails][CodeReading] Railsの初期化コードを読む (イントロ&目次)
0 件のコメント:
コメントを投稿