Rails auto loading files from wrong location - ruby-on-rails

I see lots of
LoadError: Unable to autoload constant SomeModule::MyJob expected /app/lib/some_module/my_job.rb to define it.
errors in my Rails 5.2.0 application. The part I don't understand is, why it would look inside app/lib/, since it's defined to be loaded like this in the application.rb:
config.autoload_paths << Rails.root.join('lib')
So I would expect it to load from /lib (where the module in question is located). So why is it looking inside the /app directory and how can I change it?

Change
config.autoload_paths << Rails.root.join('lib')
to
config.autoload_paths += Dir["#{Rails.root}/lib/*"]
it should work.

Related

Renaming workers per requirements of Zeitwerk (Rails 5.2.3 to 6 upgrade)

I have some Sidekiq workers that have a naming convention of like random_api_worker.rb and have the class defined as RandomAPIWorker and it has always worked up until Rails 6. In other cases, I have the classes starting off as class RandomAPIWorker although it's in a few subdirectories, such as app/workers/dir1/dir2/random_api_worker.rb
I have added config.autoloader = :classic to my application.rb file, but this seems to only do the trick if I'm running everything in development. The minute I flip the RAILS_ENV to production, then it starts complaining about worker names.
This brings me to a two questions:
Isn't the config.autoloader = :classic supposed to ignore this, or am I misunderstanding how this works?
Is there a Zeitwerk script available that could essentially upgrade classic worker names in a proper format/hierarchy?
If #1 is false, is there another way to keep my workers with their same names and not have to worry about renaming them to meet the requirements of Zeitwerk?
Here's my application.rb file:
require_relative 'boot'
require 'rails/all'
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module Vspm
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 6.0
config.autoload = :classic
config.autoload_paths << Rails.root.join('app/workers/sampleworkers/**/')
# Settings in config/environments/* take precedence over those specified here.
# Application configuration can go into files in config/initializers
# -- all .rb files in that directory are automatically loaded after loading
# the framework and any gems in your application.
config.enable_dependency_loading = true
config.eager_load_paths += Dir["#{config.root}/lib/custom/**/"]
# Add images and subdirectories to asset pipeline
config.assets.paths << "#{Rails.root}/app/assets/images/severity_icons/"
end
Here's one error (complains about the caps in one of the class names):
ubuntu#c567d17a6700:~/myapp/app$ RAILS_ENV=production rails zeitwerk:check
Hold on, I am eager loading the application.
expected file app/services/pdf_generator.rb to define constant PdfGenerator
Here's the class name defined in that file:
# app/services/pdf_generator.rb
class PDFGenerator
After fixing this, the next error complains about the directory hierarchy not being in the worker's class name:
ubuntu#c567d17a6700:~/myapp/app$ RAILS_ENV=production rails zeitwerk:check
Hold on, I am eager loading the application.
expected file app/workers/shared/random_name_worker.rb to define constant Shared::RandomNameWorker
Here's how the class is mentioned in that file:
# app/workers/shared/random_name_worker.rb
class RandomNameWorker
Isn't the config.autoloader = :classic supposed to ignore this, or am I misunderstanding how this works?
this setting config Rails back to classic mode loader on the whole app, so of course it'll ignore structure name convenient.
you could setup autoload_paths with zeitwerk, your problem is the way you add nested workers directories to autoload_paths
# NOT THIS
config.autoload_paths << Rails.root.join('app/workers/sampleworkers/**/')
# SHOULD THIS
config.autoload_paths << Rails.root.join('app/workers/sampleworkers/')
# OR THIS (if you want to use `**`)
config.autoload_paths += Dir["#{config.root}/app/workers/**/**"]
# REPLACE
config.autoloader = :classic
# BY
config.load_defaults 6.0
Is there a Zeitwerk script available that could essentially upgrade classic worker names in a proper format/hierarchy?
i don't know whether there's a gem support that or not, i haven't seen so far, i do it manually, create module each sub directories, so your worker become something like this Api_Worker::Random
# app/worker/api_worker.rb
module ApiWorker
end
# app/worker/api_worker/random.rb
module ApiWorker
class Random
include Sidekiq::Worker
end
end
If #1 is false, is there another way to keep my workers with their same names and not have to worry about renaming them to meet the requirements of Zeitwerk?
As i said above, you could extend autoload_paths with zeitwerk
config.autoload_paths += Dir["#{config.root}/app/workers/**/**"]
and you still use the name RandomAPIWorker

Rails 5.2 & Bootsnap: NameError while using app/lib file

I just upgraded to Rails 5.2 and have run into the following issues in development mode, while using a class JsonWebToken from my app/lib folder in my ApplicationController.
NameError - uninitialized constant ApplicationController::JsonWebToken:
Following the directions listed here, I have the following notable things:
I'm using bootsnap that comes by default with Rails 5.2
I no longer have a require at the top of ApplicationController since files within the app folder seem to be auto-required.
In my development.rb, I have config.eager_load = false.
In my application.rb, I have the following eager and auto loading code:
autoloads lib & policy folder during production
config.eager_load_paths << Rails.root.join('lib')
config.eager_load_paths << Rails.root.join('policies')
#autoloads lib & policy folder during development
config.autoload_paths << Rails.root.join('lib')
config.autoload_paths << Rails.root.join('policies')
If I remove bootsnap, then I have to add require 'JsonWebToken' at the top of ApplicationController, and then everything works. Bootsnap didn't like that require statement at the top.
I am not sure what is the right way to be creating or using your own classes in Rails 5.2, and to set up so that they are loaded properly in both development and production. I have gone through the Rails docs, but am extremely unclear.

Cannot load such file located in lib directory

I have been trying to set up my work environment on a new computer (ruby 1.9.3.p0 and rails 3.2.6) for the last two days and I keep getting the following error when I try to run rails server or rails console:
application.rb:7:in `require': cannot load such file -- acts_as_loggable/acts_as_loggable (LoadError)
This is what my application.rb looks like:
require File.expand_path('../boot', __FILE__)
require 'acts_as_loggable/acts_as_loggable'
require 'acts_as_abusable/acts_as_abusable'
require 'acts_as_luba/acts_as_luba'
module MyProgram
class Application < Rails::Application
config.active_record.schema_format = :ruby
# Custom directories with classes and modules you want to be autoloadable.
config.autoload_paths += %W(#{config.root}/lib/)
config.autoload_paths += %W(#{config.root}/app/models/game_mechanics)
config.autoload_paths += Dir["#{config.root}/app/admin/"]
config.autoload_paths += Dir["#{config.root}/app/models/"]
config.active_record.pluralize_table_names = true
config.action_view.sanitized_allowed_attributes = ['data-link']
My acts_as_loggable.rb file is located in lib/acts_as_loggable. All my other files load okay, except for the 3 that I left in my application.rb code sample.
If I hardcode the path/directory (see below), my app works.
require './lib/acts_as_loggable/acts_as_loggable'
require './lib/acts_as_abusable/acts_as_abusable'
require './lib/acts_as_luba/acts_as_luba'
Does anyone have any clue what is happening and how I can get my app to work without the hardcoded paths?
Thanks.
Your require is before config.autoload_path.

rails auto-include libraries issue

I want Rails to auto-include all libraries in my lib directory.
This my current configuration in config/application.rb:
config.autoload_paths += %W(#{config.root}/lib)
However, Rails will only include some of the libraries not all.
Is it maybe because library has 2 uppercases in the module name such as ModuleName?
If not, what else could it be?
Try this
config.autoload_paths += Dir["#{config.root}/lib/**/"]

classes under lib folder are not detected in rails

In my project, I have written few classes under lib folder but rails is not detecting those classes in production environment. I get the uninitalized Constant error.
I use Apache in the production environment and rails script/server in the development environment.
Is anything wrong with RAILS_ROOT environment? Can anyone suggest how to overcome this problem?
I am not sure about Rails, but you achieve that in Ruby by this: (it will work in rails too, but rails must be having some elegant way)
require File.join(File.dirname(__FILE__), "lib",'your_module_name')
include your_module_name
Try this in config/application.rb (I assume you have rails3)
config.load_paths += %W( #{config.root}/lib )
Update: Rails - why would a model inside RAILS_ROOT/lib not be available in production mode?
Ensure that the name of your file matches the name of the class or module defined in it, accounting for any directories.
ie:
lib/my_new_class.rb
class MyNewClass
end
Or if you have a directory hierarchy:
lib/my_files/my_module.rb
module MyFiles
module MyModule
end
end

Resources