LoadError: Unable to load constant

LoadError: Unable to load constant

我有一个带有 class 的模块,它与 ruby 标准库中的 class 共享一个名称。我的 class 需要调用 class 并且我遇到了 LoadError。

require 'csv'

module Generator
  class CSV
    def generate_and_write
      ::CSV.open(filename) {
        # some functionality
      }
    end
  end
end

当我调用 Generator::CSV.new.generate_and_write 时,我收到一个 LoadError 异常,指出:

Unable to autoload constant Generator::CSV, expected /app/services/generator/csv.rb to define it (LoadError)

异常来自:

vendor/bundle/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:495:in 'load_missing_constant'

调试应用程序时,加载 class:

时抛出运行时异常

::CSV = {RunTimeError} 自动加载常量 CSV 时检测到循环依赖。

我的 config/application.rbconfig.autoload_paths << Rails.root.join('app', 'services', 'generator') 以确保服务 class 与应用程序的其余部分一起自动加载。

如何在不与我的 class 的名称冲突的情况下调用标准库 CSV class?

首先,我认为 rails 的当前版本会自动加载 app/**/*,因此您不需要向自动加载添加任何内容。

其次,问题是 Rails Inflector 期望一个名为 csv.rb 的文件定义一个名为 CSV 而不是 Csv 的 class。如果您将 class 重命名为 CSV,那么它应该可以正常加载。

要在 class 中调用基础 CSV,请使用范围运算符 ::CSV 指定顶层 CSV 而不是 Generator::CSV

我通过将 Generator 模块重命名为 FileGenerators 解决了这个问题。 (我相信 FileGenerator 也能正常工作,但拥有一个复数模块更有意义,因为它包含多个 FileGenerators。)

module FileGenerators
  class CSV < FileGenerators::Base
    def generate_and_write
      ::CSV.open {
        # ...
      }
    end