升级Rails至7.1.3后运行zeitwerk:check报SvgGenerator未初始化常量错误
Rails 7.1.3升级后
rails zeitwerk:check报NameError: uninitialized constant SvgGenerator错误排查 问题描述
升级Rails应用至7.1.3版本后,执行rails zeitwerk:check命令时触发NameError: uninitialized constant SvgGenerator错误,Zeitwerk自动加载器无法找到指定常量。
错误堆栈信息
NameError: uninitialized constant SvgGenerator (NameError) parent.const_get(cname, false) ^^^^^^^^^^ /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/zeitwerk-2.6.13/lib/zeitwerk/loader/helpers.rb:135:in `const_get' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/zeitwerk-2.6.13/lib/zeitwerk/loader/helpers.rb:135:in `cget' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/zeitwerk-2.6.13/lib/zeitwerk/loader/eager_load.rb:175:in `block in actual_eager_load_dir' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/zeitwerk-2.6.13/lib/zeitwerk/loader/helpers.rb:40:in `block in ls' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/zeitwerk-2.6.13/lib/zeitwerk/loader/helpers.rb:25:in `each' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/zeitwerk-2.6.13/lib/zeitwerk/loader/helpers.rb:25:in `ls' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/zeitwerk-2.6.13/lib/zeitwerk/loader/eager_load.rb:170:in `actual_eager_load_dir' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/zeitwerk-2.6.13/lib/zeitwerk/loader/eager_load.rb:17:in `block (2 levels) in eager_load' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/zeitwerk-2.6.13/lib/zeitwerk/loader/eager_load.rb:16:in `each' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/zeitwerk-2.6.13/lib/zeitwerk/loader/eager_load.rb:16:in `block in eager_load' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/zeitwerk-2.6.13/lib/zeitwerk/loader/eager_load.rb:10:in `synchronize' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/zeitwerk-2.6.13/lib/zeitwerk/loader/eager_load.rb:10:in `eager_load' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/zeitwerk-2.6.13/lib/zeitwerk/loader.rb:379:in `block in eager_load_all' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/zeitwerk-2.6.13/lib/zeitwerk/loader.rb:377:in `each' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/zeitwerk-2.6.13/lib/zeitwerk/loader.rb:377:in `eager_load_all' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.1.3/lib/rails/zeitwerk_checker.rb:6:in `check' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.1.3/lib/rails/tasks/zeitwerk.rake:29:in `block (2 levels) in <top (required)>' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.1.0/lib/rake/task.rb:281:in `block in execute' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.1.0/lib/rake/task.rb:281:in `each' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.1.0/lib/rake/task.rb:281:in `execute' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.1.0/lib/rake/task.rb:219:in `block in invoke_with_call_chain' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.1.0/lib/rake/task.rb:199:in `synchronize' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.1.0/lib/rake/task.rb:199:in `invoke_with_call_chain' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.1.0/lib/rake/task.rb:188:in `invoke' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.1.0/lib/rake/application.rb:182:in `invoke_task' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.1.0/lib/rake/application.rb:138:in `block (2 levels) in top_level' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.1.0/lib/rake/application.rb:138:in `each' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.1.0/lib/rake/application.rb:138:in `block in top_level' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.1.0/lib/rake/application.rb:147:in `run_with_threads' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.1.0/lib/rake/application.rb:132:in `top_level' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.1.3/lib/rails/commands/rake/rake_command.rb:27:in `block (2 levels) in perform' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.1.0/lib/rake/application.rb:208:in `standard_exception_handling' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.1.3/lib/rails/commands/rake/rake_command.rb:27:in `block in perform' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.1.3/lib/rails/commands/rake/rake_command.rb:44:in `block in with_rake' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/rake-13.1.0/lib/rake/rake_module.rb:59:in `with_application' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.1.3/lib/rails/commands/rake/rake_command.rb:41:in `with_rake' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.1.3/lib/rails/commands/rake/rake_command.rb:20:in `perform' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.1.3/lib/rails/command.rb:156:in `invoke_rake' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.1.3/lib/rails/command.rb:73:in `block in invoke' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.1.3/lib/rails/command.rb:149:in `with_argv' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.1.3/lib/rails/command.rb:69:in `invoke' /Users/dmorin/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/railties-7.1.3/lib/rails/commands.rb:18:in `<top (required)>' bin/rails:9:in `require' bin/rails:9:in `<main>' Tasks: TOP => zeitwerk:check
相关代码片段
lib/rails_admin/config/actions/svg_generator.rb
require 'rails_admin/config/actions' require 'rails_admin/config/actions/base' module RailsAdmin module Config module Actions class SvgGenerator < RailsAdmin::Config::Actions::Base RailsAdmin::Config::Actions.register(self) register_instance_option :member? do true end ... end end end end
config/initializers/rails_admin.rb
require "#{Rails.root}/lib/rails_admin/config/actions/svg_generator" RailsAdmin.config do |config| config.asset_source = :sprockets ### Popular gems integration # == Devise == config.authenticate_with do warden.authenticate! scope: :user end config.current_user_method(&:current_user) # == Cancan == config.authorize_with :cancancan ## == Pundit == # config.authorize_with :pundit ## == PaperTrail == config.audit_with :paper_trail, 'User', 'PaperTrail::Version' # PaperTrail >= 3.0.0 ### More at https://github.com/sferik/rails_admin/wiki/Base-configuration ## == Gravatar integration == ## To disable Gravatar integration in Navigation Bar set to false # config.show_gravatar true config.main_app_name = ['CHU de Québec - Plans Interactifs', 'Admin'] PAPER_TRAIL_AUDIT_MODEL = %w(Point Portal Path) config.actions do dashboard # mandatory index # mandatory new export bulk_delete show edit delete show_in_app nestable svg_generator do visible do 'Hospital' == bindings[:abstract_model].model_name end end ## With an audit adapter, you can add: history_index do only PAPER_TRAIL_AUDIT_MODEL end history_show do only PAPER_TRAIL_AUDIT_MODEL end config.model Floor do nestable_list({ position_field: :index }) end end end
问题原因
- Zeitwerk加载规则冲突:Zeitwerk自动加载器会根据文件路径推断常量名,
lib/rails_admin/config/actions/svg_generator.rb对应的正确常量应为RailsAdmin::Config::Actions::SvgGenerator,但Zeitwerk在预加载时错误尝试查找顶级常量SvgGenerator,而该类实际嵌套在RailsAdmin::Config::Actions模块下。 - 语法错误影响加载:原代码中
register_instance_option :member? do块未正确闭合,导致类定义不完整,无法被正常加载。 - 手动require与自动加载冲突:在初始化文件中手动require了该文件,但Zeitwerk仍会尝试自动加载该路径下的文件,引发加载逻辑冲突。
解决方案
1. 修复代码语法错误
确保svg_generator.rb中的所有代码块正确闭合,补全register_instance_option :member?对应的end,并确保整个类的模块层级正确闭合(添加缺失的end)。
2. 让Zeitwerk忽略Rails Admin自定义动作目录
在config/application.rb中添加配置,阻止Zeitwerk自动加载lib/rails_admin目录,避免与手动加载逻辑冲突:
# 确保lib目录被加入加载路径 config.autoload_paths << Rails.root.join('lib') config.eager_load_paths << Rails.root.join('lib') # 让Zeitwerk忽略rails_admin目录 config.zeitwerk_loader.ignore(Rails.root.join('lib/rails_admin'))
3. 验证修复效果
执行以下命令验证问题是否解决:
rails zeitwerk:check
内容的提问来源于stack exchange,提问作者Denis Morin
相关产品推荐
相关产品推荐

