Spork.prefork is loading app/models/*
Asked Answered
K

4

13

I can not figure out how to get spork not to load all of my app models. Testing changes to my models is greatly slowed down as I am unable to use spork to help. This is what I get when I debug what spork is loading:

    - Spork Diagnosis -
    -- Summary --
    app/models/account.rb
    app/models/admin.rb
    app/models/affiliate.rb
    app/models/app.rb
    app/models/application_server.rb
    app/models/domain_record.rb
    app/models/domain_zone.rb
    app/models/event.rb
    app/models/oid.rb
    app/models/user.rb
    config/application.rb
    config/boot.rb
    config/environment.rb
    config/environments/test.rb
    config/initializers/api_conversions.rb
    config/initializers/backtrace_silencers.rb
    config/initializers/compass.rb
    config/initializers/devise.rb
    config/initializers/hoptoad.rb
    config/initializers/inflections.rb
    config/initializers/mime_types.rb
    config/initializers/rspec_generator.rb
    config/initializers/secret_token.rb
    config/initializers/session_store.rb
    config/routes.rb
    lib/application_server_api.rb
    lib/oid_helper.rb
    lib/soa_record.rb
    spec/spec_helper.rb



    -- Detail --



    --- app/models/account.rb ---
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:239:in `block in require'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:227:in `load_dependency'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:239:in `require'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:346:in `require_or_load'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:300:in `depend_on'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:216:in `require_dependency'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/mongoid-2.0.0.rc.7/lib/rails/mongoid.rb:54:in `load_model'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/mongoid-2.0.0.rc.7/lib/rails/mongoid.rb:17:in `block (2 levels) in load_models'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/mongoid-2.0.0.rc.7/lib/rails/mongoid.rb:16:in `each'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/mongoid-2.0.0.rc.7/lib/rails/mongoid.rb:16:in `block in load_models'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/railties-3.0.3/lib/rails/paths.rb:102:in `block in each'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/railties-3.0.3/lib/rails/paths.rb:102:in `each'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/railties-3.0.3/lib/rails/paths.rb:102:in `each'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/mongoid-2.0.0.rc.7/lib/rails/mongoid.rb:15:in `load_models'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/mongoid-2.0.0.rc.7/lib/mongoid/railtie.rb:88:in `block (2 levels) in '
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/activesupport-3.0.3/lib/active_support/callbacks.rb:419:in `_run_prepare_callbacks'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/actionpack-3.0.3/lib/action_dispatch/middleware/callbacks.rb:40:in `initialize'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/actionpack-3.0.3/lib/action_dispatch/middleware/stack.rb:33:in `new'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/actionpack-3.0.3/lib/action_dispatch/middleware/stack.rb:33:in `build'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/actionpack-3.0.3/lib/action_dispatch/middleware/stack.rb:79:in `block in build'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/actionpack-3.0.3/lib/action_dispatch/middleware/stack.rb:79:in `each'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/actionpack-3.0.3/lib/action_dispatch/middleware/stack.rb:79:in `inject'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/actionpack-3.0.3/lib/action_dispatch/middleware/stack.rb:79:in `build'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/railties-3.0.3/lib/rails/application.rb:162:in `app'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/railties-3.0.3/lib/rails/application/finisher.rb:35:in `block in '
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/railties-3.0.3/lib/rails/initializable.rb:25:in `instance_exec'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/railties-3.0.3/lib/rails/initializable.rb:25:in `run'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/railties-3.0.3/lib/rails/initializable.rb:50:in `block in run_initializers'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/railties-3.0.3/lib/rails/initializable.rb:49:in `each'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/railties-3.0.3/lib/rails/initializable.rb:49:in `run_initializers'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/railties-3.0.3/lib/rails/application.rb:134:in `initialize!'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/railties-3.0.3/lib/rails/application.rb:77:in `method_missing'
    config/environment.rb:8:in `'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:239:in `block in require'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:225:in `block in load_dependency'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:596:in `new_constants_in'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:225:in `load_dependency'
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/activesupport-3.0.3/lib/active_support/dependencies.rb:239:in `require'
    spec/spec_helper.rb:9:in `block in '
    /Users/sean/.rvm/gems/ruby-1.9.2-p136/gems/spork-0.9.0.rc3/lib/spork.rb:23:in `prefork'
    spec/spec_helper.rb:4:in `'

update: my spec_helper.rb

require 'rubygems'
require 'spork'

ENV["RAILS_ENV"] = "test"

Spork.prefork do
  require File.expand_path(File.dirname(__FILE__) + '/../config/environment')
  require 'rspec/rails'
end

Spork.each_run do
  # Hub::Application.reload_routes!
end

Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}

If I move require File.expand_path(File.dirname(__FILE__) + '/../config/environment') out of the prefork, my models are not preloaded, but as you might expect it takes much longer to run my tests.

Any ideas on how to get spork to not load models on a Rails 3 app? I have tried using spork 0.8.4, master branch, and currently 0.9.0.rc3. Does anyone have any ideas how I can avoid having the models preloaded?

Kerns answered 10/2, 2011 at 23:3 Comment(4)
I don't see this behavior, using spork 0.8.4. Are you sure your prefork block is correct?Logistic
I updated the description with my pre_fork block in my spec_helper.rbKerns
I'm still not seeing the problem. Maybe something going on in `config/environment'?Logistic
I generated a new empty Rails 3 app and my config/environment.rb and config/environments/test.rb do not differ with the new Rails 3 app's.Kerns
K
17

After much time spinning my wheels I finally have something that is acceptable:

Spork.prefork do
  require "rails/mongoid"
  Spork.trap_class_method(Rails::Mongoid, :load_models)

  # The following does not work correctly with Devise's routes that load the User model. 
  # Results in NameError unintitialized *
  # :reload_routes! triggers :devise_for which loads and caches the User class.
  # https://github.com/timcharper/spork/wiki/Spork.trap_method-Jujutsu
  # require "rails/application"
  # Spork.trap_method(Rails::Application, :reload_routes!) 

  require 'factory_girl_rails'
  Spork.trap_class_method(Factory, :find_definitions)

  require File.expand_path(File.dirname(__FILE__) + '/../config/environment')

end

The problem was mostly due to Rails::Mongoid#load_models. After inspecting the debug output of spork and the backtrace of how things are loaded, some clues are provided as to what is loading the models. This page goes into a bit more detail https://github.com/timcharper/spork/wiki/Spork.trap_method-Jujutsu, but I do not find the :reload_routes! helping with Devise forcing the User class to be preloaded.

My specs are running much faster now. If only I could get my User model to not be cached I would be in bliss, but until then, I shall be mostly satisfied.

Kerns answered 16/2, 2011 at 9:12 Comment(0)
R
8

I have the following setup in both RSpec and Cucumber on Rails 3.1 and models are refreshing:

Set factory_girls_rails require => false in your Gemfile

gem 'factory_girl_rails', :require => false

Replace the Spork.prefork and Spork.each_run blocks with the following code.

if Spork.using_spork?

  ActiveSupport::Dependencies.clear
  ActiveRecord::Base.instantiate_observers

  Spork.prefork do

  end

  Spork.each_run do
    require 'factory_girl_rails'

    # reload all the models
    Dir["#{Rails.root}/app/models/**/*.rb"].each do |model|
      load model
    end

    # reload routes
    Rails.application.reload_routes!

  end

end
Rourke answered 30/11, 2011 at 10:58 Comment(4)
This is a really nice Spork setup template to follow! It will make Spork behave the way "you expected it to in the first place". I encourage anybody reading this to follow this advice.Lough
Wow I actually thought Spork does this by default and I was always surprised when it didn't reload my models. Thanks!Cucullate
You can replace YourApp::Application.reload_routes! with Rails.application.reload_routes to make it more generic.Kirit
Good idea, i've changed the answer to use that method insteadRourke
L
7

The following solution suggested here works for me. It also reloads the User model.

# env.rb
Spork.each_run do
  require 'factory_girl_rails'
  # reload all the models
  Dir["#{Rails.root}/app/models/**/*.rb"].each do |model|
    load model
  end
end
Lough answered 19/9, 2011 at 17:33 Comment(0)
C
3

This solution works for me (from http://my.rails-royce.org/2011/03/17/rspec-2-and-fixtures/)

Spork.prefork do
  require 'rails/application'
  Spork.trap_method(Rails::Application, :reload_routes!)
  Spork.trap_method(Rails::Application::RoutesReloader, :reload!) 
  Spork.trap_method(Rails::Application, :eager_load!)
  require File.expand_path("../../config/environment", __FILE__)
  Rails.application.railties.all { |r| r.eager_load! }

  require 'rspec/rails'

  RSpec.configure do |config|
     ...
  end
end

Note that doing a "load model" in each_run is only a partial solution, this will re-evaluate the model code, but for instance after removing a model method it will still exist in memory until you restart Spork.

Caterina answered 29/6, 2012 at 11:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.