Ruby on rails 警告:引用了顶级常量
我有四种模型(Ruby on rails 警告:引用了顶级常量,ruby-on-rails,ruby,ruby-on-rails-4,Ruby On Rails,Ruby,Ruby On Rails 4,我有四种模型(Document,Question,Question::Document,和答案)。在我的答案中模型 validates :text, presence: { :unless => Proc.new{ |a| a.question.is_a? Question::Document } } 这给了我警告 警告:问题所引用的顶级常量文档::文档 如何防止发生此警告(不重命名我的类)?您的意思是: Document = 'hello' class Question end
Document
,Question
,Question::Document
,和答案
)。在我的答案中
模型
validates :text,
presence: { :unless => Proc.new{ |a| a.question.is_a? Question::Document } }
这给了我警告
警告:问题所引用的顶级常量文档::文档
如何防止发生此警告(不重命名我的类)?您的意思是:
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在指定范围内找不到常数时,会在封闭范围内搜索该常数。我认为这个警告是对不能想出两个以上变量名的惩罚 在引用有问题的
文档之前,您需要定义Question::Document
。否则Ruby将开始遍历名称空间以查找文档
。你的答案.rb
应该有
require 'question/document'
最重要的是,假设这是定义Question::Document
的路径。将各种类定义按顺序排列,以便在引用它之前定义Question::Document
。否则ruby会进入顶层,如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
你可能会看到这样的警告
/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服务器之后
,您将不会看到如此丑陋的警告
您的文件夹/文件结构应如下所示:
app/
models/
question/
document.rb
answer.rb
document.rb
question.rb
然后rails将自动找到正确的模型(它将模型名称转换为文件名,名称空间转换为文件夹)
确保在问题/document.rb中,类定义看起来是以下选项之一:
class Question::Document
end
或
如果您只编写类文档
,您将重新定义顶级常量文档
请注意,如果首先定义了全局文档
,这也会触发此错误。这取决于代码路径,因此最好的解决方法是在需要的地方添加require\u依赖项。
有关更多背景信息,请参见和
比如说
require_dependency 'question/document'
class Answer < ActiveRecord::Base
end
虽然普通的require
可以工作,但最好使用require\u dependency
,因为它可以与自动加载一起工作,这意味着:在开发过程中的行为与预期一致
在Rails中,您不应该使用“require”,因为它会弄乱自动加载
一种解决方案是在定义外部常量的文件末尾追加一个require\u依赖项
app/models/question.rb
class Question
# ...
end
require_dependency 'question/document'
class Question
class Document
# ...
end
end
app/models/question/document.rb
class Question
# ...
end
require_dependency 'question/document'
class Question
class Document
# ...
end
end
这将强制在找到Question
常量后加载Question::Document
类。通常,如果Rails已经知道顶级文档
常量,那么它不会尝试加载Question::Document
,如果它还不知道的话
参考文献:
- 在Rails指南中,介绍自动加载和重新加载常量
- 在阿皮多克
我写了一个gem,介绍了需要依赖的替代方案
解决方案:
它通过constantize
(在加载其他常量之前)在初始化时显式解析给定的常量名称。在开发过程中,每次重新加载都会发生这种情况。如果您执行以下操作会怎么样呢?::问题::文档
否。警告仍然存在我猜这只是一个开发问题,只是为了确定,需要明确定义class@KyleDecot我的答案有用吗?这里有反馈吗?已经给出了很多答案,所有这些都应该让您更接近解决方案imho。这并不是说我不能给它起个别的名字,而是说给它们起个类似的名字是有意义的,因为它们彼此相关,Question::Document
是一个以Document作为答案的问题。如果可能的话,我不想用不同的名字来命名,因为这样更容易判断两者之间的关系/联系。这段代码不是真正有效的。解析文件时执行puts Question::Document
,此时类Question::Document
尚未定义。因此,更改顺序,或者将put
放在函数中,它就会工作。同样:你的结论是错误的:“不能想出两个以上变量名的惩罚”????世界跆拳道联盟?完全有可能在不同的作用域中使用相同的类名。@nathanvda,所以更改顺序,或者将puts放在函数中,它就会工作。该示例的要点是在生成相同错误消息的某些代码中使用op提到的所有名称,而不是生成工作代码。世界跆拳道联盟?在不同的作用域中使用相同的类名是完全可能的。而且完全可以在同一范围内使用变量名xxxyxx、XXYXX、xyxxx、xxxyx。那又怎么样?目标不仅仅是编写法律语法。我们中的一些人试图将标准设置得更高一些。为什么简单的要求“问题/文档”
就不够了?加载路径将包含Rails.root.join('app/models')
,对吗?这也没关系,但我担心这个警告,所以我更喜欢使用完整路径。好的。最好指出这一点,因为将require与绝对路径一起使用是非常不习惯的。理论上这是正确的。但是在rails中,通常不会将模型放在同一个文件中(因为rails无法根据类名自动推断出文件名)。您的答案表明,要求使用正确的类来创建正确的文件应该是可行的。但是,如果Rails(4.1.5)无法正常使用(三个级别),长期的解决方案是重命名其中一个类,除非您想处理require order-esp