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

Viewed 173

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:

  1. Isn't the config.autoloader = :classic supposed to ignore this, or am I misunderstanding how this works?
  2. Is there a Zeitwerk script available that could essentially upgrade classic worker names in a proper format/hierarchy?
  3. 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
1 Answers
  1. 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 
  1. 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
  1. 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

Related