Rails 3とBundlerで左右を争ってきました。Rails アプリケーションがまだロードされていない場合、正しく動作しない gem がいくつかあります。rails3 ブランチであっても、factory_girl と shoulda はどちらも例です。shoulda を例にとると、実行しようとするrake test:units
と次のエラーが発生します。
DEPRECATION WARNING: RAILS_ROOT is deprecated! Use Rails.root instead. (called from autoload_macros at c:/code/test_harness/vendor/windows_gems/gems/shoulda-2.10.3/lib/shoulda/autoload_macros.rb:40)
c:/code/test_harness/vendor/windows_gems/gems/shoulda-2.10.3/lib/shoulda/autoload_macros.rb:44:in 'join': can't convert #<Class:0x232b7c0> into String (TypeError)
from c:/code/test_harness/vendor/windows_gems/gems/shoulda-2.10.3/lib/shoulda/autoload_macros.rb:44:in 'block in autoload_macros'
from c:/code/test_harness/vendor/windows_gems/gems/shoulda-2.10.3/lib/shoulda/autoload_macros.rb:44:in 'map'
from c:/code/test_harness/vendor/windows_gems/gems/shoulda-2.10.3/lib/shoulda/autoload_macros.rb:44:in 'autoload_macros'
from c:/code/test_harness/vendor/windows_gems/gems/shoulda-2.10.3/lib/shoulda/rails.rb:17:in '<top (required)>'
lib/shoulda/rails をもう少し深く掘り下げると、次のようになります。
root = if defined?(Rails.root) && Rails.root
Rails.root
else
RAILS_ROOT
end
# load in the 3rd party macros from vendorized plugins and gems
Shoulda.autoload_macros root, File.join("vendor", "{plugins,gems}", "*")
つまり、ここで何が起こっているかというと、Rails.root が定義されている間、Rails.root == nil が使用され、RAILS_ROOT が使用され、RAILS_ROOT==nil がそれから Shoulda.autoload_macros に渡されます。明らかに、Rails アプリはまだ初期化されていません。Rails3 で Bundler を使用するようになった今、Bundler 側で gem が必要な順序を指定できるようにするための騒ぎがありましたが、これで目前の問題が解決するかどうかはわかりません。
最終的に私の質問は次のとおりです: environment.rb ファイル (実際にアプリケーションを初期化するファイル) が取り込まれるのはいつですか? アプリが初期化され、config/application.rb の Bundler.require 行の前にそれが発生したときにバンプアップすることに害はありますか? 自分で順序を指定するためにバンドラーをハックして、最初に Rails gem を取り込もうとしましたが、Rails gem を要求しても実際にアプリケーションが初期化されるようには見えません。
アプリが初期化される前にこの行 (config/application.rb 内) が呼び出されるため、初期化するレールを必要とするバンドラー Gemfile 内のすべての gem がタンクに入れられます。
# Auto-require default libraries and those for the current Rails environment.
Bundler.require :default, Rails.env