追記: Rails, RSpec, Spork(, Guard) で適切にクラスをリロード

以前 Rails, RSpec, Spork(, Guard) で適切にクラスをリロード という記事を書いたんですが、あれだとロケールファイルをリロードしてくれないという問題があって、調べてたら、もっとシンプルな書き方ができたので、紹介します。

確認したバージョンは下記のとおり。Rails のバージョンがちょっと古いとだめかも。

  • rails 3.2.6
  • rspec 2.11.0
  • spork 0.9.2
  • guard 1.2.3

config/environment/test.rb は前回と変わりません。Spork 使うときだけ cache_classes を false にします。

# config/environment/test.rb
Blog::Application.configure do
  # Spork 使用時はクラスをキャッシュしない
  if defined?(Spork) && Spork.using_spork?
    config.cache_classes = false
  else
    config.cache_classes = true
  end
end

spec/spec_helper.rb がだいぶ簡潔になりました。

#spec/spec_helper.rb
Spork.each_run do
  if Spork.using_spork?
    # app 下のファイル / locale / routes をリロード
    # railties-3.2.3/lib/rails/application/finisher.rb あたりを参考に
    Rails.application.reloaders.each{|reloader| reloader.execute_if_updated }
    # machinist gem を利用してる場合、blueprints を再度読み直す
    # load "#{File.dirname(__FILE__)}/support/blueprints.rb"
  end
end

Rails.application.reloaders は ActionDispatch::Reloader の配列で、それぞれの条件に応じていろいろリロードしてくれます。development 環境ではこれによってクラスリロードを実現しています。

app 下のファイル、routes、ロケールファイルがリロードされることを確認しました。observer も問題なく動きます。

ActionDispatch::Reloader#execute_if_updated でなく execute というメソッドもありますが、execute_if_updated はファイルの更新の有無をチェックしてるようで、若干速いです (それなりの規模のプロジェクトで 200ms -> 40ms くらい)。Rails 3.2 で開発環境でのクラスリロードが速くなるよーって言ってたのはこれのことですね。