Rail4で困ったらSpringを停止せよ

現在、自社サービス「ゴールナビ」のRailsをv3.2からv4.1にアップグレードする作業を進めています。

その作業の中で、Spring に少し悩まされたので記録しておきます。

Springとは?

Rails4から導入されたプリローダーです。

Railsアプリケーションをあらかじめロードしておくので、railsコマンドやrakeコマンドなどの起動が速くなります。

類似のツールとしてSporkなどがありますが、Springの場合は一度セットアップすれば、すべて自動で行ってくれるので、手間が掛かりません。

Rail4での不可解なエラー

Rails4.1にアップグレードして、いくつか不可解なエラーを経験しました。

1つ目はこれです。

Unable to autoload constant User::SessionsController

RSpecを実行すると、このDeviseのコントローラーだけ、このエラーが発生。

最初はDeviseの設定やRailsのオートロードの設定に変更があったのかと思い、さんざん調べ回りましたが、結局Springの問題でした。

2つ目。

NameError: uninitialized constant PaypalExpressController

Webサーバーでページを表示しようとしたところ、特定のページのこのエラーが発生。

これもSpringが原因でした。

困ったらSpringを停止

2つのエラーのどちらも bin/spring stop を実行し、一旦Springを停止させることで解決しました。

恐らくSpringのローディング処理がおかしくなったのだと思います。

どちらのエラーもメッセージの内容からSpringを連想することは難しいので、
「困ったらSpringを停止」というのがRails4時代の教訓になるでしょう。

Springを使い分ける

Springのセットアップ手順で bundle exec spring binstub --all というものがあります。

これを実行すると、bin/railsbin/rakeなどのファイルの先頭に、Springをロードするコードが追加されます。

begin
  load File.expand_path("../spring", __FILE__)
rescue LoadError
end

そのため、bin/spring railsなどとしなくても、bin/railsとするだけで、Spring経由で実行されることになります。

ただし、これを行うと、Springを経由しないで実行させることができなくなります。

なので、場合によっては、上記のセットアップコマンドを実行しない、または、特定のコマンドだけSpringのコードを削除する、という対応を取った方が良いでしょう。

そうすれば、不具合がSpringの影響によるものかどうかすぐに調べることができます。


Ruby on Rails 4 アプリケーションプログラミング

Ruby on Rails 4 アプリケーションプログラミング