我正致力于将一个大型遗留Rails应用程序从5.2升级到6.0。在修复自动加载路径的过程中,我遇到了一个问题,Rails/Zeitwerk似乎违反了他们自己的规则,关于如何根据文件名定义常量的名称。我不能分享这个应用程序的实际代码,但实际情况是这样的:
Inconfig/application.rb
:
config.autoload_paths << "#{config.root}/app/models/coupons"
Inapp/models/coupons/burgerfrenchfry_coupon.rb
:
class BurgerfrenchfryCoupon << ApplicationRecord
end
当应用程序中的另一个类引用BurgerfrenchfryCoupon
类时,将抛出一个NameError
,并使用BurgerFrenchfryCoupon
作为建议的类名(该类在应用程序中不存在)。当我在引用BurgerfrenchfryCoupon
的文件中直接要求app/models/coupons/burgerfrenchfry_coupon
路径时,我得到一个Zeitwerk错误:Zeitwerk::NameError: expected file /redacted/app/models/coupons/burgerfrenchfry_coupon.rb to define constant BurgerFrenchfryCoupon, but didn't
我已经对应用程序进行了彻底的搜索,以找到可以自定义期望的任何地方,但我一无所获。有没有人对以下内容有什么想法?
- 为什么会发生这种情况?
- 在哪里或如何对常量名称期望进行重写?
- 我如何配置Rails来识别这个常量应该在这个文件中定义而不改变应用程序中对它的所有引用到
BurgerFrenchfryCoupon
?
问题是,由于某种原因,自动加载器的影响因子被配置为camelize "burgerfrenchfry_coupon"作为"BurgerFrenchfryCoupon"如果使用主动支持屈折(默认),在某个地方会有一些自定义屈折规则影响它。
你可以修复这个特殊的,而不影响应用程序的其余部分通过重写:
# config/initializers/autoloading.rb
inflector = Rails.autoloaders.main.inflector
inflector.inflect("burgerfrenchfry_coupon" => "BurgerfrenchfryCoupon")
在自动加载器的反射器中设置一个特殊的映射,忽略其他所有内容。
这里的答案是一个自定义的变化,已经添加到activessupport。
ActiveSupport::Inflector.inflections do |inflect|
inflect.acronym 'BurgerFrenchfry'
end
由于这个变化对于应用程序的其他部分是必需的,为了修复Zeitwerk错误,我添加了config/initializers/zeitwerk.rb
文件,内容如下:
Rails.autoloaders.each do |autoloader|
autoloader.inflector.inflect(
"burgerfrenchfry_coupon" => "BurgerfrenchfryCoupon"
)
end
覆盖这个文件
的变化