Rails模块常量无法与Zeitwerk兼容问题求助
解决方案
Zeitwerk(Rails 6+默认的自动加载器)严格遵循文件名与常量名的映射规则,你遇到的错误正是因为规则不匹配:
lib/my_app/version.rb文件,Zeitwerk会期望它定义MyApp::Version常量- 但你实际在文件里定义的是
MyApp::VERSION,因此触发Zeitwerk::NameError
以下是几种符合Zeitwerk规范的合理方案:
方案1:调整常量结构匹配命名规则
把VERSION常量放到MyApp::Version模块下,保持文件名不变:
# lib/my_app/version.rb module MyApp module Version VERSION = '3.0.7' end end
之后通过 MyApp::Version::VERSION 访问版本号,同时在application.rb中添加lib目录到自动加载路径:
# config/application.rb config.autoload_paths << Rails.root.join("lib")
方案2:将VERSION移到MyApp主模块文件
如果希望直接用MyApp::VERSION访问,把常量定义到lib/my_app.rb中:
# lib/my_app.rb module MyApp VERSION = '3.0.7' end
同样在application.rb中添加lib到自动加载路径,Zeitwerk会自动加载MyApp模块并识别VERSION常量。
方案3:通过主模块文件引入version.rb
保留现有文件结构,在MyApp主模块文件中引入version.rb:
# lib/my_app.rb module MyApp require_relative "my_app/version" end
# lib/my_app/version.rb module MyApp VERSION = '3.0.7' end
这种方式既保留了单独的version.rb文件,又让Zeitwerk加载MyApp模块时自动引入VERSION常量,无需在application.rb中直接require。
方案4:自定义Zeitwerk的文件名-常量映射
如果不想修改文件或常量结构,可通过Zeitwerk的inflector自定义映射规则:
# config/application.rb Rails.application.configure do config.autoload_paths << Rails.root.join("lib") # 让version.rb映射到VERSION常量 Rails.autoloaders.main.inflector.inflect( "version" => "VERSION" ) end
这样Zeitwerk会把lib/my_app/version.rb识别为定义MyApp::VERSION,而非MyApp::Version。
内容的提问来源于stack exchange,提问作者Kyle
相关产品推荐
相关产品推荐

