首页 > 解决方案 > 根据 Zeitwerk 的要求重命名工人(Rails 5.2.3 到 6 升级)

问题描述

我有一些 Sidekiq 工作人员,它们的命名约定为 like random_api_worker.rb,并且类定义为RandomAPIWorker,并且它一直工作到 Rails 6。在其他情况下,我的类开始时就像class RandomAPIWorker它在几个子目录中一样,例如app/workers/dir1/dir2/random_api_worker.rb

我已经添加config.autoloader = :classic到我的application.rb文件中,但这似乎只有在我运行开发中的所有内容时才有效。当我翻转RAILS_ENV到的那一刻production,它就开始抱怨工人的名字。

这给我带来了两个问题:

  1. 是不是config.autoloader = :classic应该忽略这一点,还是我误解了它的工作原理?
  2. 是否有可用的 Zeitwerk 脚本可以从本质上以适当的格式/层次结构升级经典工作人员名称?
  3. 如果 #1 为假,是否有另一种方法可以让我的工人保持相同的姓名,而不必担心重命名他们以满足 Zeitwerk 的要求?

这是我的application.rb文件:

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

这是一个错误(抱怨其中一个类名中的大写字母):

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

这是该文件中定义的类名:

# app/services/pdf_generator.rb
class PDFGenerator

修复此问题后,下一个错误抱怨目录层次结构不在工作人员的类名中:

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

以下是该文件中提到该类的方式:

# app/workers/shared/random_name_worker.rb
class RandomNameWorker

标签: ruby-on-rails

解决方案


  1. config.autoloader = :classic 不应该忽略这一点,还是我误解了它的工作原理?

这个设置配置 Rails 回到classic mode整个应用程序的加载器,所以它当然会忽略结构名称方便

你可以设置autoload_pathszeitwerk你的问题是你添加嵌套工人目录的方式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. 是否有可用的 Zeitwerk 脚本可以从本质上以适当的格式/层次结构升级经典工作人员名称?

我不知道是否有 gem 支持,到目前为止我还没有看到,我手动完成,为每个子目录创建模块,所以你的工人变成这样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. 如果 #1 为假,是否有另一种方法可以让我的工人保持相同的姓名,而不必担心重命名他们以满足 Zeitwerk 的要求?

正如我上面所说,你可以autoload_paths扩展zeitwerk

config.autoload_paths += Dir["#{config.root}/app/workers/**/**"]

你仍然使用这个名字RandomAPIWorker


推荐阅读