gpt4 book ai didi

ruby-on-rails - 尽管已在该文件中定义,但 Rails 无法从文件中自动加载常量

转载 作者:数据小太阳 更新时间:2023-10-29 06:34:49 26 4
gpt4 key购买 nike

这是一个很难解释的问题。我在另一个模块命名空间中有一个模块,如下所示:

# app/models/points/calculator.rb
module Points
module Calculator
def self.included(base)
base.send(:include, CommonMethods)
base.send(:include, "Points::Calculator::#{base}Methods".constantize)
end
end
end

那么在其他类(class)中我需要做的就是:

class User
include Points::Calculator
end

我已经在 application.rb 中指定这个目录是可自动加载的...(尽管我认为 Rails 会通过模型递归...)

config.autoload_paths += Dir[ Rails.root.join('app', 'models', "points") ]

在开发环境中,一切正常。运行测试(和生产环境)时,出现以下错误:

Unable to autoload constant Points::Calculator, expected /Users/pete/work/recognize/app/models/points/calculator.rb to define it (LoadError)

我实际上是按照这里的建议来解决问题的:Stop Rails from unloading a module in development mode通过在 application.rb 中明确要求 calculator.rb。

但是,为什么会这样呢??

我在 ActiveSupport 的 dependencies.rb 文件中插入了一些调试输出,并注意到该文件被要求两次。第一次需要它时,我可以看到常量确实已加载。

但是第二次它需要的常量就 Rails 而言已经被卸载了,但是当真正的 require 被调用时,ruby 返回 false 因为 ruby​​ 知道它已经需要它了。然后 Rails 抛出“无法自动加载常量”错误,因为常量仍然不存在并且 ruby​​ 没有“重新要求”该文件。

谁能阐明为什么会发生这种情况?

最佳答案

Rails 增强了 ruby​​ 的持续查找机制。

Ruby 中的常量查找:

类似于 method missing,当对常量的引用未能解析时,将调用 Module#constant-missing。当我们在给定的词法范围内引用常量时,会在以下位置搜索该常量:

Each entry in Module.nesting 
Each entry in Module.nesting.first.ancestors
Each entry in Object.ancestors if Module.nesting.first is nil or a module.

当我们引用一个常量时,Ruby 首先尝试根据这个内置的查找规则找到它。

ruby 找不到...时,rails 介入,并使用它自己的查找约定 及其关于哪些常量已经存在的知识加载(通过 ruby​​)后,Rails 会覆盖 Module#const_missing 以加载缺少的常量,而无需程序员显式调用 require。

它自己的查找约定?

对比 Ruby 的自动加载(需要预先指定每个自动加载常量的位置)rails 遵循将常量映射到文件名的约定。

Points::Calculator # =>points/calculator.rb

现在对于常量 Points::Calculator,rails 在自动加载路径中搜索此文件路径(即“points/calculator.rb”),该路径由 autoload_paths 配置定义。

在这种情况下,rails 在其自动加载路径中搜索文件路径 points/calculator,但找不到文件,因此显示此错误/警告。

这个答案是这个 Urbanautomation blog 的摘要.

编辑:我写了一篇关于 Zeitwerk 的博客,Zeitwerk 是 Rails 中的新代码重载器。查看 -> https://blog.bigbinary.com/2019/10/08/rails-6-introduces-new-code-loader-called-zeitwerk.html

关于ruby-on-rails - 尽管已在该文件中定义,但 Rails 无法从文件中自动加载常量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24545602/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com