Ruby on Rails-警告:引用了顶级常量

我有四个模型(warning: toplevel constant Document referenced by Question::DocumentQuestionQuestion::DocumentAnswer)。 在我的Answer模型中

validates :text,
  presence: { :unless => Proc.new{ |a| a.question.is_a? Question::Document } }

这给了我警告

warning: toplevel constant Document referenced by Question::Document

如何防止发生此警告(不重命名我的班级)?

Kyle Decot asked 2020-08-10T08:26:55Z
7个解决方案
41 votes

您的文件夹/文件结构应如下所示:

app/
  models/
    question/
      document.rb
    answer.rb
    document.rb
    question.rb

然后,Rails将自动找到正确的模型(它将模型名称转换为文件名,并将名称空间转换为文件夹)。

确保在require内部,类定义看起来是以下替代之一:

class Question::Document
end

要么

class Question
  class Document
  end
end

如果您只写require,则是在重新定义顶级常量require_dependency

请注意,如果首先定义了全局require,这也会触发此错误。 这取决于代码路径,因此解决该问题的最佳方法是在需要的地方添加require_dependency。有关更多背景,请参见此处和此处。

例如。 就像是

require_dependency 'question/document' 

class Answer < ActiveRecord::Base

end  

如果将文件放在Rails无法自动找到的其他位置,则必须明确要求它,因此Rails知道require存在。

例如,如果您在require_dependency模型中定义了require(这是一个合理的位置),则必须在Answer模型中明确声明对3004972454344393793730模型的依赖性。

因此,在这种情况下,您将在require中编写

require_dependency 'question'

class Answer < ActiveRecord::Base
  # ..
end

尽管普通require可以工作,但最好使用require_dependency代替,因为它将与自动加载一起工作,这意味着:在开发过程中按预期方式运行。

nathanvda answered 2020-08-10T08:27:45Z
20 votes

在Rails中,不应使用“ require”,因为它会干扰自动加载。

一种解决方案是将Question::Document附加到定义外部常量的文件末尾。

app / models / question.rb

class Question
  # ...
end

require_dependency 'question/document'

app / models / question / document.rb

class Question
  class Document
    # ...
  end
end

这会在找到Question常数之后强制加载Question::Document类。 通常,如果Rails已经知道顶级Document常量,那么如果未知,它将不会尝试加载Question::Document

参考文献:

  • 《 Rails自动加载和重新加载常量指南》中的示例
  • 在ApiDock的require_dependency
Steve answered 2020-08-10T08:28:36Z
5 votes

在引用违规Document参考之前,您需要定义Question::Document。 否则,Ruby将开始遍历名称空间以查找Document。您的answer.rb应该具有

require 'question/document'

在此之上,假设这是定义Question::Document的路径。

Tero Tilus answered 2020-08-10T08:29:02Z
1 votes

您可能会看到这样的警告

/path/to/app/models/answer.rb:4: warning: toplevel constant Document referenced by Question::Document

rails server被引用的类放在正在抛出的顶级文件上这个警告。

在您的情况下,以下行将进入rails server

require Rails.root.join('app/models/question/document.rb')

而且,在重新启动rails server之后,您将不会看到这种难看的警告。

您可以在此处阅读详细说明

Paritosh Piplewar answered 2020-08-10T08:29:40Z
0 votes

按顺序排列各种类定义,以便在引用Question::Document之前先对其进行定义。 否则,如7stud所示,红宝石将进入顶层。

test.rb

class Document
end

class Question
end

class Question
  class Document
  end
end

class Answer
  puts Question::Document.class
end

结果

$ ruby test.rb
Class
Fred answered 2020-08-10T08:30:09Z
0 votes

我写了一个gem,介绍了constantize解决方案的替代方案:heavy_control

它通过constantize(在加载其他常量之前)显式解析初始化时给定的常量名称。 也发生在开发中的每次重新加载。

mr_ffloyd answered 2020-08-10T08:30:34Z
-1 votes

您的意思是这样的:

Document = 'hello'

class Question
end

class Animal
  puts Question::Document
end

class Question
  class Document
  end
end

--output:--
1.rb:7: warning: toplevel constant Document referenced by Question::Document
hello

当在指定范围内找不到常量时,ruby看起来好像在范围内包围了Ruby。 我认为警告是无法思考两个以上变量名的惩罚。

7stud answered 2020-08-10T08:30:59Z
translate from https://stackoverflow.com:/questions/18515100/warning-toplevel-constant-referenced