I have a Rails application that works just fine in development. It accesses a class I have in my /lib folder due to the
config.autoload_paths += Dir["#{config.root}/lib/**/"]
line in my application.rb config file. However, when I run the application in production on Heroku, I get an Uninitialized Constant error.
For example running rails c locally:
>rails c
001> OrderPdf
=> OrderPdf
002>
but on production:
>heroku run rails c
001> OrderPdf
NameError: uninitialized constant OrderPdf
(stack trace)
002>
Whats going on here?
its because on prod you probably have this line in your config config.eager_load = true
, which loads all of your classes once before hand.
To fix this, everything that you add to the autoload_path, add to the eager_load path as well
config.eager_load_paths += Dir["#{config.root}/lib/**/"]
Related
While deploying my Rails API app to Heroku, my build is failing with the error below:
-----> Detecting rake tasks
sh: 2: Syntax error: Unterminated quoted string
sh: 2: Syntax error: Unterminated quoted string
!
! Could not detect rake tasks
! ensure you can run `$ bundle exec rake -P` against your app
! and using the production group of your Gemfile.
! rake aborted!
! NameError: uninitialized constant ApplicationPolicy
/tmp/build_64dbe116b1bd38f520ae98d49690e476/sdotapi-86210153dc2b588aa7b0dc9a60799f5090c76f46/app/policies/user_setting_policy.rb:1:in `<top (required)>'
Now, the problem is that I don't see this NameError error on my local development box. It would seem to suggest that somehow the path for my Pundit policies isn't getting loaded on Heroku but are happening on local box. But I am not sure why:
Here is the relevant part of my application.rb looks like:
config.autoload_paths << Rails.root.join('lib')
Dir[Rails.root.join('app/policies/*.rb')].each &method(:require)
The line where the error was:
class UserSettingPolicy < ApplicationPolicy
Both the policy files live in app/policies.
Any ideas on what might be going on would be super appreciated!
Found the problem finally. The policy files were getting loaded one by one in the above code and hence had to change it to below for Rails to load entire directory at once it seems.
config.autoload_paths += Dir[Rails.root.join('app', 'policies', '*.rb')]
# earlier it was Dir[Rails.root.join('app/policies/*.rb')].each &method(:require)
On a different note, the above lines in config/application.rb ended up being:
config.autoload_paths += Dir[
Rails.root.join('app', 'policies', '*.rb'),
Rails.root.join('app', 'lib', '*.rb')
]
Notice the change for lib, due to changes in autoloading in Rails 5. See here for more details: https://stackoverflow.com/a/40019108
I'm trying to use resque in my ruby on rails application.
I created resque.rake file in lib/tasks folder
require 'resque/tasks'
task 'resque:setup' => :environment
I've started redis server by following line
redis-server /usr/local/etc/redis.conf
I have this RakeFile in my application:
require_relative 'config/application'
Rails.application.load_tasks
But when I run the following command to start rake
rake resque:work QUEUE='*'
I'm getting this error:
LoadError: cannot load such file -- resque/tasks
I can't see What I'm missing,
Any suggestions ?
Thanks.
Note: I'm using rails 5.0.1
In rails you can add this in your config/application.rb
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
Don't worry this is really easy to miss in the Rails doc's. It's just a small mention on this page
Go to this page and search for "config.autoload_paths" if you'd like to read more about it.
http://guides.rubyonrails.org/autoloading_and_reloading_constants.html#autoload-paths
Also depending on how you build the app (with or without documentation) you may see comments about this in the application.rb
Rails::Initializer.run do |config|
# Add additional load paths for your own custom dirs
# config.load_paths += %W( #{RAILS_ROOT}/extras )
config.load_paths << "#{RAILS_ROOT}/app/models/some_model_group"
config.load_paths << "#{RAILS_ROOT}/lib"
end
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?
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.
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.
I am unable to run migrations in Heroku, which I believe is due to a module I created in my lib directory. After executing the command heroku run rake db:migrate I receive the below error:
uninitialized constant ApplicationController::PgTools
/app/app/controllers/application_controller.rb:4:in <class:ApplicationController>
Line 4 of the Application controller is include PgTools, which is there to gain access to methods within the PgTools module I created.
Despite the heroku migration failing, I am able to run rake db:migrate in my local dev environments without fail (please note that both environments utilize postgres databases).
I also have the following two lines in my application.rb file
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
I resolved the error by renaming Pg_Tools.rb to pgtools.rb and modifying all include PgTools statements to include Pgtools
Links that I used in the troubleshooting process are shown below
Rails 3 library not loading until require
http://www.williambharding.com/blog/technology/rails-3-autoload-modules-and-classes-in-production/
Rails 3.2.2
When running rake assets:precompile I get the following error:
uninitialized constant Redirect
Redirect is a custom middleware class that redirects naked domain requests from mydomain.com to www.mydomain.com.
I load the middleware in production.rb using:
config.middleware.use Redirect
The redirect.rb is located at lib/middleware/redirect.rb. I load the path in application.rb using:
config.autoload_paths += %W(#{config.root}/lib/middleware)
It works fine when you run the application, and other rake tasks run fine. But running rake assets:precompile appears to not load the lib properly. I first noticed the issue running on Heroku, but I've been able to reproduce locally no problem.
Any ideas? Thanks!
You probably have config.assets.initialize_on_precompile = false set somewhere.
I experienced this error after setting that configuration for something related to Heroku. To fix, i just require "#{Rails.root}/lib/my_middleware.rb" right above the line where I configure the app to use the middleware.
I was getting the same error for loading a class from /lib and assigning it to a ::GLOBAL variable.
This was because I had forgotten to place it inside an after_initialize block, which is how I had done it in development.
config.after_initialize do
::GLOBAL = MyLib::MyClass.new
end
Hope this helps somebody!