Pet*_* P. 18 ruby ruby-on-rails autoload
这是一个难以解释的问题.我在另一个模块名称空间中有一个模块,如下所示
# 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
Run Code Online (Sandbox Code Playgroud)
那么在其他课程中,我需要做的就是:
class User
include Points::Calculator
end
Run Code Online (Sandbox Code Playgroud)
我已经在application.rb中指定了这个目录可以自动加载...(尽管我认为rails通过模型进行递归...)
config.autoload_paths += Dir[ Rails.root.join('app', 'models', "points") ]
Run Code Online (Sandbox Code Playgroud)
在开发环境中,一切正常.运行测试(和生产环境)时,我收到以下错误:
Unable to autoload constant Points::Calculator, expected /Users/pete/work/recognize/app/models/points/calculator.rb to define it (LoadError)
Run Code Online (Sandbox Code Playgroud)
我实际上遵循了这里的建议来解决问题:通过在application.rb中明确要求calculator.rb,阻止Rails在开发模式下卸载模块.
但是,为什么会发生这种情况?
我在ActiveSupport的dependencies.rb文件中粘贴了一些调试输出,并注意到这个文件需要两次.第一次需要我可以看到常量确实已加载.
但是第二次它需要的常量已被卸载,就Rails而言,但是当调用实际的require时,ruby返回false,因为ruby知道它已经需要它.然后Rails抛出"无法自动加载常量"错误,因为常量仍然不存在,并且ruby没有"重新要求"该文件.
任何人都可以阐明为什么会发生这种情况?
Rails增强了ruby的常量查找机制.
Ruby中的常量查找:
类似于method missing,Module#constant-missing当对常量的引用无法解析时,会调用a.当我们在给定的词法范围中引用常量时,会在以下位置搜索该常量:
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.
Run Code Online (Sandbox Code Playgroud)
当我们引用一个常量时,Ruby首先尝试根据这个内置的查找规则找到它.
当ruby无法找到... rails并使用its own lookup convention它并且知道已经加载了哪些常量(通过ruby)时,Rails会覆盖Module#const_missing加载缺少的常量,而不需要程序员明确的require调用.
它自己的查找约定?
对比Ruby的自动加载(需要事先指定每个自动加载常量的位置),遵循将常量映射到文件名的约定.
Points::Calculator # =>points/calculator.rb
Run Code Online (Sandbox Code Playgroud)
现在对于常量Points :: Calculator,rails在autoload_paths配置定义的自动加载路径中搜索此文件路径(即'points/calculator.rb').
在这种情况下,rails points/calculator在其自动加载的路径中搜索文件路径,但无法找到文件,因此显示此错误/警告.
这个答案是Urbanautomation博客的摘要.
Calculator应该是一个可以正确自动加载的类
module Points
class Calculator
...
end
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9877 次 |
| 最近记录: |