Rails 自动加载:常量在测试之间丢失或引入循环依赖

Rails autoloading: constants are lost between tests or a circular dependency is introduced

我 运行 遇到了 Rails 自动加载在 development/test 环境中的工作方式的问题。我想要实现的是一种父级 class 的可插入实现,可以在应用程序启动时修改。更详细地说,我用以下想法实现了 class Measure

# app/models/measure.rb
class Measure

  attr_reader :implementations

  def self.register(klass)
    @implementations << klass
  end

  def self.from(raw_value)
    # ... find a suitable implementation and instantiate it
  end

  # ...
end

然后我有不同 Measures 的实现,例如:

# app/models/measures/grams.rb
module Measures
  class Grams < Measure
    # ... code to tell Measures if this class can be 
    # instantiated from a given raw value
  end
end

然后应使用 Measure.register(Measures::Grams) 等调用来设置这些。

问题是,如果我在初始化程序中执行此操作,则度量实现会在测试 运行 之间丢失,因为常量缓存显然已被清除。这意味着,像 Measure.from("2 grams") 这样应该有效的调用不再有效,因为 Measure.implementations 不包含 Measures::Grams。另一方面,如果我在 app/models/measure.rb 中添加一个 require_dependency,引用一些执行注册的代码,那么在 Rails 加载之前引用其中一个实现时,我有一个循环依赖Measureclass。经过相当多的摆弄和阅读 Rails 如何自动加载之后,我一直无法想出一个令人满意的解决方案。

所以我的问题是:应该如何设置此层次结构才能与 Rails 自动加载代码的方式相得益彰?

看来我找到了解决这个问题的方法,将跟踪已注册实现的责任从 Measure 基础 class 转移到 Measures 模块,并且还在定义模块的同一文件中进行注册。在我看来,这也是一个更合理的架构选择。唯一剩下要做的就是用 's' 词缀来区分名称。