rails 7 个 zietwerk 常量未找到
rails 7 zietwerk constants not found
我正在将我们的应用程序从 rails 6 升级到 7,我使用的是 zeitwerk 而不是带有 rails 6 的经典自动加载器,没有任何问题,现在对 [=56 没有任何更改=] 命名约定或结构它无法在 lib 文件夹中找到任何 classes/modules。我一直在调试 zeitwerk gem 并且自动加载哈希将文件路径作为键,将 [Namespace, Constant Name]
作为值,rails 6 它具有正确的名称 space,例如对于 \user\project\rails6_test\lib\folder\config.rb
中的文件,它的名称为 Folder
,space 和 config.rb
中定义的 Config
将在 Folder
名称中正确找到space 但在使用 rails 7 迁移后,它总是以 Object
作为名称 space,不仅适用于顶级文件夹,而且适用于所有嵌套文件,显然它不能在 Object
.
中找到这些常量
我没有看到升级指南中遗漏的任何内容,这里可能遗漏了什么?
更新
我试过 运行 bin/rails r 'pp ActiveSupport::Dependencies.autoload_paths'
但我得到以下错误,
/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader/callbacks.rb:25:in `on_file_autoloaded': expected file /home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/restful_resource.rb to define constant RestfulResource, but didn't (Zeitwerk::NameError)
raise Zeitwerk::NameError.new("expected file #{file} to define constant #{cpath}, but didn't", cref.last)
^^^^^
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/kernel.rb:28:in `require'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader/helpers.rb:95:in `const_get'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader/helpers.rb:95:in `cget'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader.rb:238:in `block (2 levels) in eager_load'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader/helpers.rb:26:in `block in ls'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader/helpers.rb:18:in `each_child'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader/helpers.rb:18:in `ls'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader.rb:233:in `block in eager_load'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader.rb:218:in `synchronize'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader.rb:218:in `eager_load'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader.rb:318:in `each'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader.rb:318:in `eager_load_all'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/application/finisher.rb:78:in `block in <module:Finisher>'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/initializable.rb:32:in `instance_exec'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/initializable.rb:32:in `run'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/initializable.rb:61:in `block in run_initializers'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/3.1.0/tsort.rb:228:in `block in tsort_each'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/3.1.0/tsort.rb:350:in `block (2 levels) in each_strongly_connected_component'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/3.1.0/tsort.rb:431:in `each_strongly_connected_component_from'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/3.1.0/tsort.rb:349:in `block in each_strongly_connected_component'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/3.1.0/tsort.rb:347:in `each'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/3.1.0/tsort.rb:347:in `call'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/3.1.0/tsort.rb:347:in `each_strongly_connected_component'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/3.1.0/tsort.rb:226:in `tsort_each'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/3.1.0/tsort.rb:205:in `tsort_each'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/initializable.rb:60:in `run_initializers'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/application.rb:372:in `initialize!'
from /home/leonidas/projects/ruby_on_rails/rainman/config/environment.rb:5:in `<top (required)>'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/kernel.rb:35:in `require'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/kernel.rb:35:in `require'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/application.rb:348:in `require_environment!'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/command/actions.rb:28:in `require_environment!'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/command/actions.rb:15:in `require_application_and_environment!'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/commands/runner/runner_command.rb:33:in `perform'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/thor-1.2.1/lib/thor/command.rb:27:in `run'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/thor-1.2.1/lib/thor/invocation.rb:127:in `invoke_command'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/thor-1.2.1/lib/thor.rb:392:in `dispatch'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/command/base.rb:87:in `perform'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/command.rb:48:in `invoke'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/commands.rb:18:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'
我的 application.rb 中有 config.autoload_paths << "#{config.root}/lib"
,为了使用 zeitwerk 测试预加载,我添加了 config.eager_load_paths += Dir["#{config.root}/lib/**/"]
,如果您需要更多信息,请告诉我。
更新 2
用 /lib
运行 bin/rails r 'pp ActiveSupport::Dependencies.eager_load_paths'
去掉通配符后得到以下输出
["/home/leonidas/projects/ruby_on_rails/project_name/lib",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/microservices/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/microservices/dir/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/dir/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/dir/dir/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/dir/dir/dir/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/dir/dir/dir/dir/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/dir/dir/dir/dir/dir/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/dir/dir/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/dir/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/dir/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/dir/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/tasks/",
"/home/leonidas/projects/ruby_on_rails/project_name/app/controllers",
"/home/leonidas/projects/ruby_on_rails/project_name/app/mailers",
"/home/leonidas/projects/ruby_on_rails/project_name/app/models",
"/home/leonidas/projects/ruby_on_rails/project_name/app/serializers",
"/home/leonidas/projects/ruby_on_rails/project_name/app/workers",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/actionmailbox-7.0.2.2/app/controllers",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/actionmailbox-7.0.2.2/app/jobs",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/actionmailbox-7.0.2.2/app/models",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/activestorage-7.0.2.2/app/controllers",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/activestorage-7.0.2.2/app/controllers/concerns",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/activestorage-7.0.2.2/app/jobs",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/activestorage-7.0.2.2/app/models",
"/home/leonidas/projects/ruby_on_rails/project_name/spec/mailers/previews"]
和运行 bin/rails r 'pp ActiveSupport::Dependencies._eager_load_paths'
输出以下
{"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/activestorage-7.0.2.2/app/controllers",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/activestorage-7.0.2.2/app/controllers/concerns",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/activestorage-7.0.2.2/app/jobs",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/activestorage-7.0.2.2/app/models",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/actionmailbox-7.0.2.2/app/controllers",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/actionmailbox-7.0.2.2/app/jobs",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/actionmailbox-7.0.2.2/app/models",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/actiontext-7.0.2.2/app/helpers",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/actiontext-7.0.2.2/app/models",
"/home/leonidas/projects/ruby_on_rails/project_name/app/controllers",
"/home/leonidas/projects/ruby_on_rails/project_name/app/mailers",
"/home/leonidas/projects/ruby_on_rails/project_name/app/models",
"/home/leonidas/projects/ruby_on_rails/project_name/app/serializers",
"/home/leonidas/projects/ruby_on_rails/project_name/app/workers",
"/home/leonidas/projects/ruby_on_rails/project_name/lib"}
我正在查看 rails 中的 zeitwerk.rake
任务,它似乎不检查自动加载路径中存在的任何现有目录和非空目录,但不在急切加载路径中,我不明白这里应该发生什么,autoload_paths
不应该有扩展的文件夹结构并且只列出根文件夹吗?因为在我的例子中,自动加载也有嵌套的目录,并且 eager_load 只有根目录正在打印关于不检查 lib 中的文件夹的警告。
感谢您的更新。问题是这个 glob:
config.eager_load_paths += Dir["#{config.root}/lib/**/"]
添加到预加载路径,也添加到自动加载路径(我觉得这有点令人困惑,但它是如何工作的)。因此,该 glob 正在将 lib/project_name
添加到自动加载路径。理解正在发生的事情的关键观察是,当存在嵌套的根路径时,the most nested one wins 就其下方的文件和目录而言。
因此,由于 lib
在自动加载路径中,因此假定 lib
以下的任何内容都在 Object
中定义。但是,由于 lib/project_name
也在自动加载路径中,该子树也代表 Object
。这与您在 app/models
和 app/models/concerns
.
中遇到的情况相同
These docs 解释一下,但在这种情况下它们很容易被忽略,因为您的配置受该点影响并不明显。
解决方法是只添加lib
:
config.autoload_paths << "#{config.root}/lib"
config.eager_load_paths << "#{config.root}/lib"
就这样,没有通配符。从技术上讲,相对于第二行,第一行是多余的,但在我看来,这是微妙且不明显的,我个人喜欢将两者都明确化,但如您所愿。 (不会有重复条目,最终集合通过uniq
。)
既然我们在上面,让我也评论一些额外的东西。也许您的应用程序已经这样做了,但为了以防万一,让我说 lib
通常有不打算自动加载的文件和目录。例如,lib/tasks
。仔细考虑它们并告诉自动加载器是干净的:
Rails.autoloaders.main.ignore("#{config.root}/lib/tasks")
否则,自动加载器将认为 lib/tasks
是一个命名空间,将为 Tasks
在 Object
中定义一个自动加载,如果是急切的,将急切加载(==实际定义)模块加载已启用等。从概念上讲,lib/tasks
没有要加载的代码 autoloaded/eager,配置必须反映这一点。与其他类似目录相同。
我正在将我们的应用程序从 rails 6 升级到 7,我使用的是 zeitwerk 而不是带有 rails 6 的经典自动加载器,没有任何问题,现在对 [=56 没有任何更改=] 命名约定或结构它无法在 lib 文件夹中找到任何 classes/modules。我一直在调试 zeitwerk gem 并且自动加载哈希将文件路径作为键,将 [Namespace, Constant Name]
作为值,rails 6 它具有正确的名称 space,例如对于 \user\project\rails6_test\lib\folder\config.rb
中的文件,它的名称为 Folder
,space 和 config.rb
中定义的 Config
将在 Folder
名称中正确找到space 但在使用 rails 7 迁移后,它总是以 Object
作为名称 space,不仅适用于顶级文件夹,而且适用于所有嵌套文件,显然它不能在 Object
.
我没有看到升级指南中遗漏的任何内容,这里可能遗漏了什么?
更新
我试过 运行 bin/rails r 'pp ActiveSupport::Dependencies.autoload_paths'
但我得到以下错误,
/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader/callbacks.rb:25:in `on_file_autoloaded': expected file /home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/restful_resource.rb to define constant RestfulResource, but didn't (Zeitwerk::NameError)
raise Zeitwerk::NameError.new("expected file #{file} to define constant #{cpath}, but didn't", cref.last)
^^^^^
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/kernel.rb:28:in `require'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader/helpers.rb:95:in `const_get'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader/helpers.rb:95:in `cget'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader.rb:238:in `block (2 levels) in eager_load'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader/helpers.rb:26:in `block in ls'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader/helpers.rb:18:in `each_child'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader/helpers.rb:18:in `ls'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader.rb:233:in `block in eager_load'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader.rb:218:in `synchronize'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader.rb:218:in `eager_load'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader.rb:318:in `each'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/loader.rb:318:in `eager_load_all'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/application/finisher.rb:78:in `block in <module:Finisher>'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/initializable.rb:32:in `instance_exec'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/initializable.rb:32:in `run'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/initializable.rb:61:in `block in run_initializers'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/3.1.0/tsort.rb:228:in `block in tsort_each'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/3.1.0/tsort.rb:350:in `block (2 levels) in each_strongly_connected_component'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/3.1.0/tsort.rb:431:in `each_strongly_connected_component_from'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/3.1.0/tsort.rb:349:in `block in each_strongly_connected_component'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/3.1.0/tsort.rb:347:in `each'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/3.1.0/tsort.rb:347:in `call'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/3.1.0/tsort.rb:347:in `each_strongly_connected_component'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/3.1.0/tsort.rb:226:in `tsort_each'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/3.1.0/tsort.rb:205:in `tsort_each'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/initializable.rb:60:in `run_initializers'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/application.rb:372:in `initialize!'
from /home/leonidas/projects/ruby_on_rails/rainman/config/environment.rb:5:in `<top (required)>'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/kernel.rb:35:in `require'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/zeitwerk-2.5.4/lib/zeitwerk/kernel.rb:35:in `require'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/application.rb:348:in `require_environment!'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/command/actions.rb:28:in `require_environment!'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/command/actions.rb:15:in `require_application_and_environment!'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/commands/runner/runner_command.rb:33:in `perform'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/thor-1.2.1/lib/thor/command.rb:27:in `run'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/thor-1.2.1/lib/thor/invocation.rb:127:in `invoke_command'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/thor-1.2.1/lib/thor.rb:392:in `dispatch'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/command/base.rb:87:in `perform'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/command.rb:48:in `invoke'
from /home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/railties-7.0.2.2/lib/rails/commands.rb:18:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'
我的 application.rb 中有 config.autoload_paths << "#{config.root}/lib"
,为了使用 zeitwerk 测试预加载,我添加了 config.eager_load_paths += Dir["#{config.root}/lib/**/"]
,如果您需要更多信息,请告诉我。
更新 2
用 /lib
运行 bin/rails r 'pp ActiveSupport::Dependencies.eager_load_paths'
去掉通配符后得到以下输出
["/home/leonidas/projects/ruby_on_rails/project_name/lib",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/microservices/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/microservices/dir/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/dir/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/dir/dir/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/dir/dir/dir/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/dir/dir/dir/dir/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/dir/dir/dir/dir/dir/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/dir/dir/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/dir/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/dir/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/project_name/dir/",
"/home/leonidas/projects/ruby_on_rails/project_name/lib/tasks/",
"/home/leonidas/projects/ruby_on_rails/project_name/app/controllers",
"/home/leonidas/projects/ruby_on_rails/project_name/app/mailers",
"/home/leonidas/projects/ruby_on_rails/project_name/app/models",
"/home/leonidas/projects/ruby_on_rails/project_name/app/serializers",
"/home/leonidas/projects/ruby_on_rails/project_name/app/workers",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/actionmailbox-7.0.2.2/app/controllers",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/actionmailbox-7.0.2.2/app/jobs",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/actionmailbox-7.0.2.2/app/models",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/activestorage-7.0.2.2/app/controllers",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/activestorage-7.0.2.2/app/controllers/concerns",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/activestorage-7.0.2.2/app/jobs",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/activestorage-7.0.2.2/app/models",
"/home/leonidas/projects/ruby_on_rails/project_name/spec/mailers/previews"]
和运行 bin/rails r 'pp ActiveSupport::Dependencies._eager_load_paths'
输出以下
{"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/activestorage-7.0.2.2/app/controllers",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/activestorage-7.0.2.2/app/controllers/concerns",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/activestorage-7.0.2.2/app/jobs",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/activestorage-7.0.2.2/app/models",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/actionmailbox-7.0.2.2/app/controllers",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/actionmailbox-7.0.2.2/app/jobs",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/actionmailbox-7.0.2.2/app/models",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/actiontext-7.0.2.2/app/helpers",
"/home/leonidas/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/actiontext-7.0.2.2/app/models",
"/home/leonidas/projects/ruby_on_rails/project_name/app/controllers",
"/home/leonidas/projects/ruby_on_rails/project_name/app/mailers",
"/home/leonidas/projects/ruby_on_rails/project_name/app/models",
"/home/leonidas/projects/ruby_on_rails/project_name/app/serializers",
"/home/leonidas/projects/ruby_on_rails/project_name/app/workers",
"/home/leonidas/projects/ruby_on_rails/project_name/lib"}
我正在查看 rails 中的 zeitwerk.rake
任务,它似乎不检查自动加载路径中存在的任何现有目录和非空目录,但不在急切加载路径中,我不明白这里应该发生什么,autoload_paths
不应该有扩展的文件夹结构并且只列出根文件夹吗?因为在我的例子中,自动加载也有嵌套的目录,并且 eager_load 只有根目录正在打印关于不检查 lib 中的文件夹的警告。
感谢您的更新。问题是这个 glob:
config.eager_load_paths += Dir["#{config.root}/lib/**/"]
添加到预加载路径,也添加到自动加载路径(我觉得这有点令人困惑,但它是如何工作的)。因此,该 glob 正在将 lib/project_name
添加到自动加载路径。理解正在发生的事情的关键观察是,当存在嵌套的根路径时,the most nested one wins 就其下方的文件和目录而言。
因此,由于 lib
在自动加载路径中,因此假定 lib
以下的任何内容都在 Object
中定义。但是,由于 lib/project_name
也在自动加载路径中,该子树也代表 Object
。这与您在 app/models
和 app/models/concerns
.
These docs 解释一下,但在这种情况下它们很容易被忽略,因为您的配置受该点影响并不明显。
解决方法是只添加lib
:
config.autoload_paths << "#{config.root}/lib"
config.eager_load_paths << "#{config.root}/lib"
就这样,没有通配符。从技术上讲,相对于第二行,第一行是多余的,但在我看来,这是微妙且不明显的,我个人喜欢将两者都明确化,但如您所愿。 (不会有重复条目,最终集合通过uniq
。)
既然我们在上面,让我也评论一些额外的东西。也许您的应用程序已经这样做了,但为了以防万一,让我说 lib
通常有不打算自动加载的文件和目录。例如,lib/tasks
。仔细考虑它们并告诉自动加载器是干净的:
Rails.autoloaders.main.ignore("#{config.root}/lib/tasks")
否则,自动加载器将认为 lib/tasks
是一个命名空间,将为 Tasks
在 Object
中定义一个自动加载,如果是急切的,将急切加载(==实际定义)模块加载已启用等。从概念上讲,lib/tasks
没有要加载的代码 autoloaded/eager,配置必须反映这一点。与其他类似目录相同。