web-dev-qa-db-ja.com

警告:参照されるトップレベル定数

4つのモデル(DocumentQuestionQuestion::Document、およびAnswer)。私のAnswerモデルには

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

これは私に警告を与えます

warning: toplevel constant Document referenced by Question::Document

クラスの名前を変更せずに、この警告が発生しないようにするにはどうすればよいですか?

41
Kyle Decot

フォルダ/ファイル構造は次のようになります。

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

そしてRailsは自動的に正しいモデルを見つけます(モデル名をファイル名に変換し、名前空間をフォルダーに変換します)。

question/document.rb内で、クラス定義が次の選択肢の1つとして見えることを確認してください。

class Question::Document
end

または

class Question
  class Document
  end
end

class Documentだけを記述した場合、トップレベル定数Documentを再定義しています。

グローバルDocumentが最初に定義されている場合、このエラーもトリガーされることに注意してください。これはコードパスに依存するため、それを解決する最善の方法は、必要に応じてrequire_dependencyを追加することです。 here および here を参照してください。

例えば。何かのようなもの

require_dependency 'question/document' 

class Answer < ActiveRecord::Base

end  

Railsが自動的に見つからない別の場所にファイルを配置する場合、明示的に要求する必要があるため、RailsはQuestion::Documentが存在することを知っています。

たとえば、合理的な場所であるQuestionモデル内でQuestion::Documentを定義する場合、QuestionモデルへのAnswerモデルへの依存関係を明示的に指定する必要があります。

したがって、その場合は、answer.rbに次のように記述します。

require_dependency 'question'

class Answer < ActiveRecord::Base
  # ..
end

単純なrequireは機能しますが、自動ロードで機能するため、代わりにrequire_dependencyを使用することをお勧めします。つまり、開発中に期待どおりに動作します。

40
nathanvda

Railsでは、自動読み込みを台無しにするため、「require」を使用することは想定されていません。

これに対する解決策の1つは、require_dependencyから外部定数を定義するファイルのend.

app/models/question.rb

class Question
  # ...
end

require_dependency 'question/document'

app/models/question/document.rb

class Question
  class Document
    # ...
  end
end

これにより、Question::DocumentQuestion定数が見つかった後にロードされるクラス。通常、RailsがトップレベルのDocument定数を既に知っている場合、Question::Documentまだ知られていない場合。

参照:

19
Steve

Question::Document違反のあるDocument参照を参照する前に定義されています。それ以外の場合RubyはDocumentを見つけるために名前空間の走査を開始します。あなたのanswer.rb すべきだった

require 'question/document'

その上で、それがQuestion::Documentが定義されています。

5
Tero Tilus

このような警告が表示される場合があります

/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このようない警告は表示されません。

ここで詳細な説明を読むことができます

1

さまざまなクラス定義を順番に配置して、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
0
Fred

require_dependencyソリューションの代替案を紹介するgemを書きました: heavy_control

constantizeを介して(他の定数がロードされる前に)初期化時に指定された定数名を明示的に解決します。また、開発中にリロードが発生します。

0
mr_ffloyd