Severin
Severin

Reputation: 8588

NameError: uninitialized constant on Heroku

I have a Rails 5 application with some modules/classes located under /lib. In development I can access those through the rails console like so:

irb(main):001:0> MyClass.do_something

In Production on Heroku I get this:

irb(main):001:0> MyClass.do_something
NameError: uninitialized constant MyClass

As you might have guessed I autoload the /lib directory in my application.rb:

config.autoload_paths << Rails.root.join('lib')

However, the most curious thing about this is, that I can access this class from rake tasks. So something like this works fine:

task do_something: :environment do
  MyClass.do_something
end

Which tells me that the class is present on Heroku.

Any ideas?

Upvotes: 5

Views: 2795

Answers (2)

Jmf
Jmf

Reputation: 437

I have been puzzled why all of my objects were uninitialized constant in console on heroku in production. In my local production, they were fine.

Turns out that the problem was that I was running: "heroku run console" not "heroku run rails console".

Worth noting that when you access console from the heroku website, the same problem occurs there too. Wasted a lot of time on this.

Upvotes: 0

m. simon borg
m. simon borg

Reputation: 2575

Rails doesn't autoload in production for thread safety, instead eager loading application constants. You can fix your issue by using the eager_load_paths method instead.

config.eager_load_paths << Rails.root.join('lib')

If you still want to autoload in development you can make it conditional

load_path_strategy = Rails.env.production? ? :eager_load_paths : :autoload_paths
config.public_send(load_path_strategy) << Rails.root.join('lib')

If you really need autoloading of this directory in production you can set enable_dependency_loading to true.

config.enable_dependency_loading = true
config.autoload_paths << Rails.root.join('lib')

See this blog post for more explanation.

Upvotes: 9

Related Questions