警告:toplevel常量引用

Kyl*_*cot 42 ruby ruby-on-rails ruby-on-rails-4

我有四个模型(Document,Question,Question::DocumentAnswer).在我的Answer模型中,我有

validates :text,
  presence: { :unless => Proc.new{ |a| a.question.is_a? Question::Document } }
Run Code Online (Sandbox Code Playgroud)

这给了我警告

warning: toplevel constant Document referenced by Question::Document

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

nat*_*vda 41

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

app/
  models/
    question/
      document.rb
    answer.rb
    document.rb
    question.rb
Run Code Online (Sandbox Code Playgroud)

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

确保question/document.rb类定义中的内容看起来是以下替代方案之一:

class Question::Document
end
Run Code Online (Sandbox Code Playgroud)

要么

class Question
  class Document
  end
end
Run Code Online (Sandbox Code Playgroud)

如果你只是写,class Document你正在重新定义顶级常数Document.

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

比如像

require_dependency 'question/document' 

class Answer < ActiveRecord::Base

end  
Run Code Online (Sandbox Code Playgroud)

如果将文件放在不同的位置,rails无法自动找到它,则必须明确要求它,因此rails知道Question::Document存在.

例如,如果您Question::DocumentQuestion模型内部定义(这是一个合理的位置),则必须在Question模型中明确说明对模型的依赖性Answer.

所以,在那种情况下,answer.rb你会写下来

require_dependency 'question'

class Answer < ActiveRecord::Base
  # ..
end
Run Code Online (Sandbox Code Playgroud)

虽然普通的require工作原理,但最好使用require_dependency它,因为它可以用于自动加载,这意味着:在开发过程中表现如预期.

  • 从最新版本的rails开始,如果有任何东西首先加载​​顶级Document,这实际上并不起作用.如果发生这种情况,Rails只会抛出一个错误并拒绝查找正确的文件,如果你尝试访问它后面的Question :: Document. (2认同)

Ste*_*eve 20

在Rails中,你不应该使用"require",因为它会弄乱自动加载.

对此的一个解决方案是将a附加require_dependency到定义外部常量的文件的末尾.

应用程序/模型/ question.rb

class Question
  # ...
end

require_dependency 'question/document'
Run Code Online (Sandbox Code Playgroud)

应用程序/模型/问题/ document.rb

class Question
  class Document
    # ...
  end
end
Run Code Online (Sandbox Code Playgroud)

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

参考文献:


Ter*_*lus 5

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

require 'question/document'
Run Code Online (Sandbox Code Playgroud)

在它之上,假设Question::Document是定义的路径.