【问题标题】:Class name conflict between Rails app and RakeRails 应用程序和 Rake 之间的类名冲突
【发布时间】:2017-08-16 21:13:05
【问题描述】:

我的 Rails 4 应用程序中有一个 Document 模型,它的开头如下:

class Document < ActiveRecord::Base
  TYPES = [FileList, Article, VariantList, LinkedItemsList].collect(&:model_name)
  ...
end

TYPES 数组包含我的应用程序中的其他模型列表,并在一些地方使用,例如在我的一个表单中显示可能的文档类型列表。

现在我正在编写一个 Rake 任务来自动化一些东西,当我运行该任务时,我在 Document 模型的第 2 行收到了这个错误:

NoMethodError: undefined method 'model_name' for Rake::FileList:Class

显然,首先加载了Rake::FileList 类,但我遇到了名称冲突。在我的代码中使用 ::FileList 没有帮助,我得到了同样的错误。

知道如何在不重命名模型的情况下解决这个问题吗?

更新:

我的 Rake 任务定义如下所示:

namespace :store do
  desc 'Some description'
  task :my_task_name, [:a_parameter_name] => [:environment] do |t, args|
    ...
  end
end

我认为这是正确加载环境,因为我在到达 Document 之前调用(从 DB 加载)一些其他模型并且工作正常。

【问题讨论】:

  • 在您的 rake 任务中,您是否正在加载环境?喜欢task mytask: :environment do
  • @JCorcuera 我用我的任务定义更新了我的问题

标签: ruby-on-rails ruby rake


【解决方案1】:

您可以尝试在类定义的末尾给它一个别名FileList

class FileList < ActiveRecord::Base
  ...
end

FileListCopy = FileList

然后在您的 rake 访问中访问FileListCopy

【讨论】:

  • 试过了,我命名了别名 DocumentFileList 并在我的TYPE 数组中更改它,但我现在得到NameError: uninitialized constant DocumentFileList
【解决方案2】:

当您从 Document 模型调用 FileList 时,它会尝试按以下顺序解析此常量:

  1. 它试图在Module.nesting 链的元素中找到常数。在您的情况下,嵌套只是 [Document],它不包含 FileList 常量。
  2. 然后它尝试在对象的祖先中查找常量。
  3. 最后在Object 中查找常量。

Rake 通过扩展 ObjectRake::DSL 模块在全球范围内公开其 DSL。因此,在使用 rake 时,您总是会从 rake 中获得FileList

要解决此问题,您可以将所有代码移至命名空间。例如MyApp::FileListMyApp::Document。在这种情况下,常量查找算法将尝试在嵌套元素中查找常量 ([MyApp::Document, MyApp])。嵌套的第二个元素 (MyApp) 包含 FileList 常量。因此,它将从MyApp 模块而不是Rake 解决。

为避免此类问题,将代码放入某个命名空间总是一个好主意。

【讨论】:

  • 感谢您的详尽解释。我意识到我可以将我的模型放入命名空间,但这不是您通常对 Rails 模型所做的事情,除非它们在引擎中。我把它作为最后的手段,因为我不想只为这种情况引入命名空间。
猜你喜欢
  • 2013-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多