3

I've a class defined as such:

class PublicationJob < ActiveJob::Base
  def self.jobs
    @jobs ||= Hash{|h, k| h[k] = []}
  end
  def self.register(format, job_class)
    jobs[format] << job_class
  end
  # [...]
end

To register different job classes, I put in an initializer:

PublicationJob.register(:tex, SaveJob)
PublicationJob.register(:saved_tex, TexJob)
#...

The in the rails console I try:

PublicationJob.jobs
#> {:tex => [SaveJob], :saved_tex => [TexJob]}

But if I exit the console (Ctrl-D) then restart it, at some point the hash will be empty!

Why is the class variable reset in this case?

I use rails 4.2.1 and spring, and I know that if I kill/stop spring it works again for some time. Is it related to spring?

Jaffa
  • 12,442
  • 4
  • 49
  • 101
  • 1
    Are you making modifications to files? Because spring reloads these files, and even restarts the application in some cases, causing your data to get wiped. – codingbunny Apr 17 '15 at 08:38
  • I update some files in the app directory, but not even the publication_job :/ – Jaffa Apr 17 '15 at 08:46
  • yeah, that could be enough for Spring to reload your app, depending on what you have changed. Thus wiping your data – codingbunny Apr 17 '15 at 08:51
  • But if spring reloads the app, then why doesn't it reload the initializer as well ? – Jaffa Apr 17 '15 at 08:52
  • look at https://github.com/rails/spring#class-reloading it explains why the data changes. – codingbunny Apr 17 '15 at 08:55
  • Thanks a lot. "So to avoid this problem, don't save off references to application constants in your initialization code." In other words, this mean I can't initialize my application. Great ! – Jaffa Apr 17 '15 at 09:06

2 Answers2

2

Okay, so this was entirely Spring related, and I fixed it by removing spring.

Thanks to @NekoNova who pointed me to the right part of the documentation, I found that:

This saves off the first version of the User class, which will not be the same object as User after the code has been reloaded:

[...]

So to avoid this problem, don't save off references to application constants in your initialization code.

In other words, I can't initialize my classes using initializers, because althought it'll work in production, it won't work in development.

Community
  • 1
  • 1
Jaffa
  • 12,442
  • 4
  • 49
  • 101
2

I know this is rather old, but I have encountered this issue a couple of times, and feel that you don't have to abandon spring if you set class level variables at initialization.

All you need to do is re-assign them in a spring ".after_fork" block. So for the above issue, place in a "config/spring.rb" file, the following:

if ("Spring".constantize rescue nil)
  Spring.after_fork do
    PublicationJob.register(:tex, SaveJob)
    PublicationJob.register(:saved_tex, TexJob)
  end
end

This will reset those variables after spring completes the fork and reloading code. I wrap it in a check to ensure that Spring is available, which it likely won't be in production.

Tom H
  • 207
  • 2
  • 13