升级到 Rails 6 时,有一种编程方式可以检测 Zeitwerk::NameError?

There is a programmatical way to detect Zeitwerk::NameError when upgrading to Rails 6?

我目前正在将旧的 Rails 应用程序迁移到 Rails 6.

项目中的某些文件似乎与其中定义的类不一致。 我在 运行 测试应用程序时没有看到此错误,但在部署后我收到如下错误:

 Zeitwerk::NameError: expected file /app/my?_/app/lib/multi_io.rb to define constant MultiIo, but didn't

在之前的 SO 问题中,我可以找到以下建议:

我不是在寻找解决方法,所以我更正了引发异常的文件。

我想找到一种编程方式来检测所有不一致的 path/class 名称,而无需 运行 在生产模式下运行应用程序。

到目前为止,我想到了三个选项:

  1. 用于验证自动加载的 rake 任务(not provided by the gem)。它存在吗?您是否可以从开发环境中的 rails 控制台获取 运行 的代码片段?
  2. rubocop cop 或其他静态代码分析器。有吗?
  3. 在测试环境中强制预加载

无需多次验证我的代码的建议方法是什么 iterations/deployments?

非常感谢您

您可以使用 zeitwerk::check 任务检查项目的自动加载兼容性:

$ bin/rails zeitwerk:check
Hold on, I am eager loading the application.
All is good!

它会执行所有自动加载路径,并将标记由常量名称推断的变化(例如带有首字母缩略词的问题)引起的问题。除升级指南外,该任务似乎没有被广泛宣传或记录。但是,实际上我有时会使用它来清除项目中的常量命名问题(即 class 与文件不匹配的地方)。

@rmlockerd 在他的回答 .

中描述了最好的工具之一 bin/rails zeitwerk:check

我发现的其他文章有:

我采取的过程是 运行 bin/rails zeitwerk:check 修复错误,运行 再次修复,直到我看到“一切都很好”。之后解决了我们的规范测试报告的错误。

要解决的一个普遍问题是,如果文件夹不在 Rails 默认文件结构中,Zeitwerk 在自动加载时将无法找到它。我们有一个名为“services”(app/services)的文件夹,需要将其添加到 application.rb 文件中的自动加载路径,例如:

config.autoload_paths += %W(#{config.root}/app/services/)

错误:

Expected file path/file_name.rb to define constant FileName

Fix: 删除引用 class 定义的其他文件中的任何 requirerequire_relative(Zeitwerk 不需要它们)。

错误(class定义在子目录的模块内):

NameError: uninitialized constant SubFile::ClassName

Fix:

在另一个 S/O 答案中有详细说明。每当在子文件夹中使用方法时,调用结构为 Folder::SubDirectory::Class.method_call

祝你好运!