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