我有四个模型(Document
,Question
,Question::Document
和Answer
)。在我的Answer
模型中,我有
validates :text,
presence: { :unless => Proc.new{ |a| a.question.is_a? Question::Document } }
这给了我警告
warning: toplevel constant Document referenced by Question::Document
如何防止发生此警告(不重命名我的课程)?
答案 0 :(得分:40)
您的文件夹/文件结构应如下所示:
app/
models/
question/
document.rb
answer.rb
document.rb
question.rb
然后rails将自动找到正确的模型(它会将模型名称转换为文件名,名称空间将转换为文件夹)。
确保question/document.rb
类定义中的内容看起来像下列其中一种:
class Question::Document
end
或
class Question
class Document
end
end
如果你只是写class Document
,那么你正在重新定义顶级常数Document
。
请注意,如果首先定义全局Document
,则也会触发此错误。这取决于代码路径,因此解决这个问题的最佳方法是在需要的地方添加require_dependency
。
有关更多背景信息,请参阅here和here。
E.g。
之类的东西require_dependency 'question/document'
class Answer < ActiveRecord::Base
end
如果您将文件放在其他位置,rails无法自动找到它,则必须明确要求它,因此rails知道Question::Document
存在。
例如,如果您在Question::Document
模型中定义Question
,这是一个合理的位置,您必须明确说明{{1}模型中的Question
模型的依赖关系模型。
那么,在这种情况下,在你的Answer
中你会写
answer.rb
虽然普通
require_dependency 'question' class Answer < ActiveRecord::Base # .. end
有效,但最好使用require
,因为它可以自动加载,这意味着:在开发过程中表现如预期。
答案 1 :(得分:18)
在Rails中,你不应该使用“require”,因为它会弄乱自动加载。
对此的一个解决方案是将require_dependency
附加到定义外部常量的文件的 end 。
应用/模型/ question.rb 强>
class Question
# ...
end
require_dependency 'question/document'
应用/模型/问题/ document.rb 强>
class Question
class Document
# ...
end
end
这会强制在找到Question::Document
常量后加载Question
类。通常情况下,如果Rails已经知道顶级Document
常量,那么如果它还不知道,它将不会尝试加载Question::Document
。
<强>参考文献:强>
答案 2 :(得分:5)
在引用违规Question::Document
引用之前,您需要定义Document
。否则Ruby将开始遍历名称空间以查找Document
。您的answer.rb
应该
require 'question/document'
在它之上,假设这是定义Question::Document
的路径。
答案 3 :(得分:1)
你可能会看到像这样的警告
/path/to/app/models/answer.rb:4: warning: toplevel constant Document referenced by Question::Document
只有require
引用的类,在顶部文件上投掷
这个警告。
在您的情况下,以下行将进入app/model/answer.rb
require Rails.root.join('app/models/question/document.rb')
并且,重新启动rails server
后,您将看不到这种丑陋的警告。
答案 4 :(得分:0)
按顺序放置各种类定义,以便在引用之前定义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
答案 5 :(得分:0)
我写了一个宝石,介绍require_dependency
解决方案的替代方案:heavy_control
通过constantize
(在加载其他常量之前)明确地解决了关于初始化的常量名称。它也会在开发中重新加载。
答案 6 :(得分:-1)
你的意思是这样的:
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搜索包含范围的常量。我认为警告是因为无法想到两个以上的变量名称而受到惩罚。