【问题标题】:NameError: uninitialized constant AppName::Loader::ModelImport::MyModelNameError:未初始化的常量 AppName::Loader::ModelImport::MyModel
【发布时间】:2019-12-19 05:03:38
【问题描述】:

我有一个命名空间问题。 MyModel 只是一个普通的 Rails 模型。但是,我的代码似乎是在我创建的命名空间下对其进行命名空间,我需要一种方法来直接引用它而不使用 AppName::Loader::ModelImport 命名空间。

错误:

NameError: 未初始化的常量 AppName::Loader::ModelImport::MyModel

耙任务:

require 'csv'
require_relative '../appname/loader/model_import'


namespace :app_name do
  namespace :loader do

    desc "Loads data into Database"

    task model_import: :environment  do

      include AppName::Loader::ModelImport
    end
  end
end

服务对象

./appname/loader/model_import.rb

module AppName
  module Loader
    module ModelImport
      record_set = []

      file_name = File.join(Rails.root, 'lib','appname','loader','data' ,'data.txt')
      CSV.open(file_name, "r", { :col_sep => "\t", quote_char: nil, row_sep: "\r\r\n" }).each do |row|
        record_set << MyModel.new(
          company_name: row[1],
          address1: row[2],
          address2: row[3],
          city: row[4],
          state_code: row[5],
          zip_code: row[6]
          )
      end

      MyModel.import record_set
    end
  end
end

我试过了:

::MyModel.new()

并且还得到了 >>NameError: uninitialized constant MyModel,所以我想知道 rails 是否没有正确加载。但是,我认为task model_import: :environment do 会加载 Rails。

我的 application.rb 文件有..

    config.eager_load_paths << Rails.root.join("lib")

如果我使用 Pry,我可以看到“Rails”常量已加载。但是,我无法访问我的任何模型。例如,User 不会加载,也不会加载其他任何内容。

Tom Lord 的每个 cmets 的解决方案:

需要在加载环境后进行评估。

【问题讨论】:

  • ./appname/loader/model_import.rb 从您的 Rails 项目的根目录开始吗?
  • 在我的应用程序 lib/appname/loader/model_import.rb 的 lib 文件夹中
  • 命名空间的目的是什么?您只需在模块内编写代码。但为什么呢?
  • 我认为发生的事情是require_relative 语句正在立即评估文件。而且由于这发生在环境加载之前,它不知道MyModel 是什么。
  • 总结...回答您提出的实际问题:您可以使用::MyModel 而不是MyModel 明确地说“使用顶级命名空间”。但是,这实际上并不能解决您的问题;你问错问题了。相反,您需要做的是确保在加载环境后评估代码。 (例如,通过在模块中实际定义一个方法,并在 rake 任务中调用它。或者,通过将 require_relative 移动到 take 任务中。)

标签: ruby-on-rails ruby ruby-on-rails-5


【解决方案1】:

如果您编写一个模块,其中的代码可能会因为您需要该模块而自动执行。例如:

module AppName
  module Loader
    module ModelImport
      puts 'wtf' # this may get run but you won't see it
    end
  end
end

但是,如果您至少定义了方法,则可以调用它

module AppName
  module Loader
    module ModelImport
      def self.wtf
        puts 'wtf'
      end
    end
  end
end

现在如果这个文件保存在lib/app_name/loder/model_import.rb 你可以这样运行它:

require_or_load 'lib/app_name/loader/model_import'
# and now you can do
AppName::Loader::ModelImport.wtf
=>wtf

所以你需要先定义一个可用的模块,然后你可以要求它,然后你可以调用它的方法。

【讨论】:

  • 虽然你是对的,但我认为 OP 所指的问题是一个持续的查找问题,例如MyModel vs ::MyModel @TomLord 提到的
  • 很好的推荐,我都做了,移动了我的需求,并添加了一个新方法。现在可以使用了
猜你喜欢
  • 1970-01-01
  • 2015-01-19
  • 2015-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-04
  • 2016-06-12
  • 2015-03-01
相关资源
最近更新 更多