Reloading models in Rails 3.1 when usign Spork and cache_classes = true

Speeding up you tests with Spork is very common when developping Rails applications.

What Spork do is preloading your application in a server and copies a fork of that server whenever you run tests.

It avoids reloading all the rails stack !! That is great !!!

But the problem I ran into is that I wanted to be able to

  • reload my application files
  • and keep cache_classes = true

That is why I like ruby and rails (and great coders there ! ). What I simply did :

  1. Reading and understanding the rails initialize process  (especially these lines engine.rb and finisher.rb )
  2. Adding these small pieces of code in my prefork block with Spork trap method 
  3. trap eager loading in my prefork block like below
  require 'rails/application'
  # Use of
  Spork.trap_method(Rails::Application, :reload_routes!)
  Spork.trap_method(Rails::Application::RoutesReloader, :reload!)
  require 'rails/mongoid'
  Spork.trap_class_method(Rails::Mongoid, :load_models)
  # Prevent main application to eager_load in the prefork block (do not load files in autoload_paths)
  Spork.trap_method(Rails::Application, :eager_load!)
  # Below this line it is too late...
  require File.expand_path("../../config/environment", __FILE__)
  # Load all railties files
  Rails.application.railties.all { |r| r.eager_load! }

My own benefits : specs runs faster than setting cache_classes = false

You need small explanation of what I’ve done !

  Spork.trap_method(Rails::Application, :eager_load!)
  require File.expand_path("../../config/environment", __FILE__)
  Rails.application.railties.all { |r| r.eager_load! }

First, we prevent Rails::Application to loads files in the application autoload_paths such as app/models, app/controllers etc …

  Spork.trap_method(Rails::Application, :eager_load!)

Second, we load the rails stack :

  require File.expand_path("../../config/environment", __FILE__)

Last, we eager load all the engines :

  Rails.application.railties.all { |r| r.eager_load! }

Doing that we can make change in our models and avoid restarting spork.

Why don’t I just set cache_classes to false ?

Because the ActiveSupport::Dependencies.mechanism is set to :require and not :load

All application files are required and not just loaded (spork required them just after forking, not before).
This trick could resolve some inconsistencies in your application (such as already defined constant and else …)

6 thoughts on “Reloading models in Rails 3.1 when usign Spork and cache_classes = true

  1. Thank you for this post!
    I was getting erros when setting cache_class to false when using spork and factory_girl_rails, but also needing to reload models and controllers on each run.
    Solved with your solution!


  2. Thanks, thats the first setup that works for me (using DataMapper). All the other suggestions i found e.g. on stackoverflow didnt work.

Leave a Reply

Your email address will not be published. Required fields are marked *