Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

spork + rspec-2 + rails-3 doesn't reload models by default #37

Closed
dchelimsky opened this issue Jun 3, 2010 · 41 comments
Closed

spork + rspec-2 + rails-3 doesn't reload models by default #37

dchelimsky opened this issue Jun 3, 2010 · 41 comments

Comments

@dchelimsky
Copy link
Contributor

I just got rspec-2 working with spork and rails-3. I haven't had a chance to investigate why yet, but with this configuration we need to set config.cache_classes = false to get models to reload. This suggests that rails is eager loading models during the prefork (which in my case is not asking to load anything under app). Something we can manage from spork?

@timcharper
Copy link
Contributor

Great news. Yes, I'm betting models are getting preloaded. It's a nasty duck punch to make spork do it's magic with Rails, unfortunately. I'm hoping the Rails 3 cleans up it's architecture. I'm dreading figuring out how to get the tests running with Bundler... there's so much uncertainty around it still.

@dchelimsky
Copy link
Contributor Author

Are you at RC this week?

@timcharper
Copy link
Contributor

No, at home.

@petRUShka
Copy link

What should I do to avoid this issue?

If I set config.cache_classes to false I have very many test fails of my apps.

@timcharper
Copy link
Contributor

I pushed spork 0.8.4 out, it includes a patch contributed by Elliot Winkler that fixes the bundler/spork conflict with the diagnoser mode.

Can you run spork -d and see what's preloading it? We must intervene, with the best means available, to make the application not preload the models.

Tim

@petRUShka
Copy link

My system:
ruby 1.9.3dev (2010-05-08 trunk 27674) [x86_64-linux]
spork (0.8.4)

$ spork -d > out.txt

https://gist.github.com/bfb318c6375c444ed395

And my spec_helper: https://gist.github.com/1d92348b08b71a5fc798
I runned spork. Then I added error in my user.rb.
I run rspec with --drb and get no error. Then I run rspec without drb and saw an error.


$ rspec spec/models/user_spec.rb --drb
...
Finished in 0.0281 seconds
3 examples, 0 failures
$ rspec spec/models/user_spec.rb
/usr/lib/ruby/gems/svn/gems/activerecord-3.0.0.beta3/lib/active_record/base.rb:1141:in method_missing': undefined methods' for #Class:0x0000000474caa8 (NoMethodError)

@thibaudgg
Copy link

same problem that petRUShka with Ruby 1.8.7 & Rails 3.0.0.beta4 (config.cache_classes to false => many test fails) and model modification not reloaded.

my spork -d: http://gist.github.com/435745

@dpickett
Copy link

I can confirm this issue with the latest version of REE (2010.02) - model modifications are not reloaded

@anlek
Copy link

anlek commented Jun 25, 2010

I have a similar issue, however only some models are reloading. My User model does not reload, but my Order model does...
(using REE 2010.02)
my spork -d: http://gist.github.com/452989
I'm also using Mongoid instead of ActiveRecord

@thibaudgg
Copy link

Any news about the resolution of this problem?

@timcharper
Copy link
Contributor

No, but I did just get the spork cucumber testsuite to work with bundler (as in, it can test with a rails project generated using a bundler gemfile)! This is, in my opinion, a HUGE step forward and has been a primary hold-back rails 3.0 support.

@thibaudgg
Copy link

Great to hear that, thk for the update!

@timcharper
Copy link
Contributor

OK... so spork totally isn't compatible with rails 3.0 right now. It's been using the Unknown framework, which basically leaves you on your own to make stuff you want loaded each time is done in an each_run block....

@thibaudgg
Copy link

It'll be easy to fix?

@MSch
Copy link
Contributor

MSch commented Jul 9, 2010

For me this solution does reload models: http://github.com/rspec/rspec-core/issues/issue/62/#issue/62/comment/305544

@mat813
Copy link

mat813 commented Sep 1, 2010

Same here, the solution on the rspec-core issues works for me too.
Would be great now that rails 3.0 is out of the closet that spork worked with it :-)

@timcharper
Copy link
Contributor

All interested parties: try out 0.9.0 RC2. At least the integration tests show that model reloading is occurring.

I've still got some doubts about observers triggering pre-loading of models, and have noticed that mongoid seems to want to eagerload the model universe as well.

Tim

@mat813
Copy link

mat813 commented Sep 13, 2010

So, do we have to remove the fix from http://github.com/rspec/rspec-core/issues/issue/62/#issue/62/comment/305544 after we've upgraded to 0.9.0 RC2 ? or else ?

@timcharper
Copy link
Contributor

Hmm, I don't know. Try it and see? (it shouldn't be preloading application files.. although some things may still trigger it).

It seems like it's best to avoid preloading any application files (app// and lib/), but I can see the merit in that being an easy, reliable solution (although it feels a little messy).

... so... you tell me?

@mat813
Copy link

mat813 commented Sep 13, 2010

Ok, so, I upgraded to 0.9.0.rc2, removed the fix from the rspec-core issue 62's comment, and I ran the tests once, changed a model so that some tests should fail, and with spork, the model was not reloaded, it was still giving me a all's ok result, restarting spork gives me the errors I was expecting, correcting the model back still gives me the errors.
Putting back the fix gives me back the expected result.
So, all in all, no, not fixed :-)

@timcharper
Copy link
Contributor

OK :) there's likely something else triggering the models to load during boot. Do you have observers loaded? Can you post the interesting pieces from the result of `spork -d'

@mat813
Copy link

mat813 commented Sep 13, 2010

No observers. Here's the spork -d output :

Using RSpec
Preloading Rails environment
Loading Spork.prefork block...
- Spork Diagnosis -
-- Summary --
config/application.rb
config/boot.rb
config/environment.rb
config/environments/test.rb
config/initializers/backtrace_silencers.rb
config/initializers/devise.rb
config/initializers/haml.rb
config/initializers/inflections.rb
config/initializers/mime_types.rb
config/initializers/new_rails_defaults.rb
config/initializers/secret_token.rb
config/initializers/session_store.rb
config/routes.rb
spec/spec_helper.rb
vendor/plugins/dynamic_form/lib/action_view/helpers/dynamic_form.rb
vendor/plugins/jrails/lib/jquery_selector_assertions.rb
vendor/plugins/jrails/lib/jrails.rb

@timcharper
Copy link
Contributor

huh, I'll be. It doesn't show that you're models are being preloaded (scratches head until bald spot occurs)

I'm seriously stumped here.

@wakiki
Copy link

wakiki commented Sep 15, 2010

I'm also using rspec 2 / Rails 3.0.0 / Spork '0.9.0.rc2' and it is not reloading models either. I can't use the hack above because I'm also using database_cleaner with my Capybara/Selenium Webdriver tests - gives me a wierd TypeMismatch error - somehow the classes are defined twice.

I resorted to doing the following:

Spork.each_run do

This code will be run each time you run your specs.

Force-load all the app files.

Ugly spork hack because it doesn't work with Rails 3 - remove as soon as spork is fixed

silence_warnings do
Dir["#{Rails.root}/app/*/.rb"].each { |f| load f }
end
end

@wakiki
Copy link

wakiki commented Sep 15, 2010

spork -d didn't reveal anything but I think I've found out where the models are being preloaded - via factory_girl

I did this by placing the following lines on top of one of my models (person.rb), and then tail'ed the test.log:

begin
raise
rescue => e
Rails.logger.info [e, e.backtrace].join("\n")
end

http://pastie.org/private/vheva2yln2qtfywhwrtqw

I wonder if it's possible to trap the method like you do for other things...

Steve

@timcharper
Copy link
Contributor

So weird that it is preloaded but not showing up in your `spork -d'. I'll have to try and play around with a test project and see if I can reproduce here.

Trapping the method seems like the best approach. The find_definitions method looks like the best bet.

Try this:

Spork.trap_class_method(Factory, :find_definitions)

Put it so it gets called before the environment is loaded, and after factory_girl is loaded (you may need to manually require...)

@wakiki
Copy link

wakiki commented Sep 15, 2010

OK I've figured it out.

It was factory_girl_rails that was causing the preload (which wasn't picked up by spork -d) but it is required as a gem so I moved the gem to its own 'development' only group so it isn't loaded by spork prefork:

group :development do
gem 'spork', '0.9.0.rc2'
gem 'factory_girl_rails'
end

When it comes to spec_helper I manually require it myself (I put all my factories in spec/factories) - you might change that:

Spork.each_run do
require 'factory_girl'
Dir[File.expand_path(File.join(File.dirname(FILE),'factories','*','.rb'))].each {|f| require f}
end

The models seem to reload properly now.

@Cluster444
Copy link

One problem I had once i finally got spork to reload my models properly was that I could not run a db:reset. I got errors complaining about factory girl not being able to find my database tables, which makes sense since the reset just dropped them!

With the changes in the comment above I no longer needed to load FG within any of the Gemfile groups so i made a separate group that still gets loaded by bundler, but doesn't load FG in any of my environments, leaving spork to load it manually.

group :noload do
  gem 'factory_girl_rails'
end

I'm still not exactly sure what caused db:reset to flip out, but this little hack fixed it.

@jgadbois
Copy link

I'm having this same problem with factory girl.

I can't require factory_girl in each_run because I get an error

Exception encountered: #<LoadError: no such file to load -- factory_girl>

Very frustrating. Any suggestions?

@Cluster444
Copy link

https://github.com/Cluster444/zmchapters/blob/74df4d6bb85d3cf25afae028302a6b23d5d07700/spec/spec_helper.rb

https://github.com/Cluster444/zmchapters/blob/74df4d6bb85d3cf25afae028302a6b23d5d07700/Gemfile

That's how i've setup factory girl and it seems to work ok. I've only ever run into a problem with my User model not reloading, the rest of them reload fine.

@ozzyaaron
Copy link

Hi there, this is the code I settled on with a co-worker today and it seems to do the trick. Put it in application.rb :

ActionDispatch::Callbacks.after do      
  # Reload the factories
  return unless (Rails.env.development? || Rails.env.test?)

  unless Factory.factories.blank? # first init will load factories, this should only run on subsequent reloads
    Factory.factories.clear
    Factory.find_definitions.each do |location|
      Dir["#{location}/**/*.rb"].each { |file| load file }
    end
  end

end    

@nishant-n
Copy link

This is my Spork.prefork block
{Spork.prefork do
require File.expand_path(File.join(File.dirname(FILE),'..','config','environment'))
require 'spec/autorun'
require 'ruby-debug'
require 'webrat'
require 'webrat/integrations/rspec-rails'
require 'db/seeds'
require 'authlogic/test_case/mock_request'
require 'authlogic/test_case/mock_cookie_jar'
require 'authlogic/test_case/mock_controller'
require 'merchant/utils'
include Merchant::Utils
end}
when i ran spork -d its only show loaded confin/initializers/..files and spec_helper ......why?
is the same issue?

@FooBarWidget
Copy link

I've written a wiki entry on this: https://github.com/timcharper/spork/wiki/Troubleshooting

@jc00ke
Copy link

jc00ke commented Sep 3, 2011

I can verify that the suggestion in the wiki does not solve the problem with FactoryGirl 2.1.0 & Rails 3.1. I found it necessary to reload all the models, otherwise changes would not be picked up.

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

I'll update the wiki article now.

@morr
Copy link

morr commented Oct 1, 2011

I found it necessary to reload all the models, otherwise changes would not be picked up.

This solution works but I'm getting a lot of warnings on every test run because i have constants defined in my models

/home/morr/develop/site/app/models/group_join_policy.rb:2: warning: already initialized constant Free
/home/morr/develop/site/app/models/group_join_policy.rb:7: warning: already initialized constant ByOwnerInvite

@timcharper
Copy link
Contributor

The problem is the models are getting preloaded. Spork states that any code that is preloaded will be cached from run to run. Use spork -d | less to get a report of what files are loaded, and a stack trace of what was responsible for triggering the load.

@mmriis
Copy link

mmriis commented Oct 24, 2011

I just :

Spork.each_run do
  require 'factory_girl_rails'
end

And in my Gemfile :

gem 'factory_girl_rails', :require => false

@dtuite
Copy link

dtuite commented Oct 28, 2011

+1 on @jc00ke 's last comment. I tried everything else in this thread to no avail on Rails 3.1.1 with FactoryGirl. I have to explicitly reload all the models.

When I run spork -d | less it doesn't say that it's loading app/models prefork.

Finally, once I add foreman or guard into the mix, event @jc00ke 's advice doesn't fix the issue :-(

@evanrmurphy
Copy link

I also rely on a workaround like wakiki and jc00ke's to make models reload with spork:

Spork.each_run do
  ...
  # Hack to ensure models get reloaded by Spork - remove as soon as this is fixed in Spork.
  # Silence warnings to avoid all the 'warning: already initialized constant' messages that
  # appear for constants defined in the models.
  silence_warnings do
    Dir["#{Rails.root}/app/models/**/*.rb"].each {|f| load f}
  end
end

Edit: got silence_warnings to work

@apux
Copy link

apux commented Sep 2, 2012

Is this issue solved?, I'm using 1.0.0rc and get the same behavior.

@apux
Copy link

apux commented Sep 2, 2012

Ok, I switched to fork-rails and it works now.

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests