Tiny Tip: Spork not reloading classes

I have no clue what caused this today, but when I went to run Guard, which monitors files in my Ruby on Rails project, Spork was behaving badly.  I would go into a model, put in a “debugger” line and then save the file.  Guard picked up the file fine, but Spork was not reloading the class or hitting the break point.

I tried all sorts of things, including restarting Spork a dozen times, tried running it without Guard and then again with Guard, and nothing was working.  The kicker is that the last time I ran all of this, it worked flawlessly.  And even going through my git repository and looking at each commit, I couldn’t figure out what changed.

In the end I found a StackOverflow thread that pointed me to the fix, but I’m not very happy with it.  To fix it, all I did was change my spec_helper.rb Spork.each_run to look like this:

Spork.each_run do
  FactoryGirl.reload
  ActiveSupport::Dependencies.clear
end

I added line 3 to clear out the classes on each run.

Anyone have an idea why I should suddenly need to do this? Spork has always worked for me without doing this before…

UPDATE: I figured out what happened, because it just happened again.  Turns out if you have

config.cache_classes = true

defined in your test.rb file, then spork just simply won’t reload models, controllers, anything. Even if you add the each_run line I posted about above. In fact, that each_run line might not even be necessary. This is sort of a pain, but I ended up doing this instead:

config.cache_classes = !(ENV['DRB'] == 'true')

This line sets the cache_classes to false if the DRB environment variable (set by spork) is true. This way, you don’t cache during spork testing, but can still cache during full regression testing. I find if I don’t turn on caching during regression I have a TON of problems where objects aren’t matching and the like.

But that is why my problem just suddenly appeared! I must have turned caching on and suddenly, everything stopped working as expected.

comments
12 comments
  1. Stephan says:

    That helped me a lot. Thanks!

  2. Gerry says:

    Setting:
    config.cache_classes = !(ENV['DRB'] == ‘true’)

    fixed the issue for me, huge thanks! Although just like in your case it seemed to happen all of a sudden for no reason. Thing is, I hadn’t been anywhere near that option in months (if ever on this project) so that was not what caused it for me. Perhaps caching only kicks in once a certain requirement has been reached?

  3. You can use `spork –diagnose` to see which files Spork loads upon initialisation. In general it should not load anything in the `app/` or `lib/` folders.

    I had a case where Draper was loading all my models and had to put `Spork.trap_class_method(Draper::System, :load_app_local_decorators)` in the `Spork.prefork` in my spec_helper.

    Cheers.

  4. LF says:

    I just ran into the same issue:
    It *seemed* like spork stopped reloading files, but actually I did just make changes in a file that got preloaded by devise. The other files I edited were reloaded normally. It turned out that the Spork trap method was invoked too late in the test_helper.rb . After moving the trap-call further up, the model got reloaded on each run.

    I have cache_classes turned on and will leave it like that.

  5. Magne says:

    Thanks! This solved the annoying problem that suddenly occurred. I hadn’t made any changes to the test.rb file though. Spork must have hit some threshold, as mentioned in another comment.

  6. Joe Siefers says:

    Make sure that you only have one Spork instance running. For some reason I had another hanging around which explains why the issue appeared suddenly, out of the blue. Once I killed it the issue went away…

  7. Mark Hurwitz says:

    Just figuring out that my classes weren’t loading was difficult. This saved me a lot of time, thanks!

  8. Ahhh thanks so much for posting this!!

  9. Chris Salzberg says:

    In case anyone else finds this… my problem was slightly more obscure. I had specified a class in a FactoryGirl factory, and this, it turns out, causes the model to be preloaded, so that spork then cannot reload it each run.

    From the docs:

    Another thing to watch out for with Factory Girl is when specifying a class for a factory, using a class constant will cause the model to be preloaded in prefork preventing reloading, whereas using a string will not.

    https://github.com/sporkrb/spork/wiki/Spork.trap_method-Jujitsu

    So the solution is just to replace the class with a string… so simple.

  10. reyesyang says:

    Thanks for your article, the root cause is that factory_girl_rails will load factory definition automaticly,so it pre-load related models. We can use Spork.trap_class_method(FactoryGirl, :find_definitions) to solve this problem now. Reference: https://github.com/sporkrb/spork/wiki/Spork.trap_method-Jujitsu. ; )

  11. I caused a similar problem for myself by referencing one of my models from a factory like this:

    factory :daily_datum do
    start_time TimeOfDay.new(“12:44:41″)
    end

    The factory works but now the “TimeOfDay” class won’t reload automatically. The solution is simply to only refer to the TimeOfDay within a block (note the curly braces for start_time’s value):

    factory :daily_datum do
    start_time { TimeOfDay.new(“12:44:41″) }
    end

    Now TimeOfDay will reload automatically without any other special measures.

  12. Dave Sanders says:

    In general, that’s how I think it works. Anytime you want to do something dynamic, you need to have it interpreted at run-time by putting it in a block. Outside a block it gets used on that initial load. I’ve definitely seen similar issues with any other Time or Date objects.

Leave a comment

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>