4つのモデル(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
クラスの名前を変更せずに、この警告が発生しないようにするにはどうすればよいですか?
フォルダ/ファイル構造は次のようになります。
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
を使用することをお勧めします。つまり、開発中に期待どおりに動作します。
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::Document
Question
定数が見つかった後にロードされるクラス。通常、RailsがトップレベルのDocument
定数を既に知っている場合、Question::Document
まだ知られていない場合。
参照:
Question::Document
違反のあるDocument
参照を参照する前に定義されています。それ以外の場合RubyはDocument
を見つけるために名前空間の走査を開始します。あなたのanswer.rb
すべきだった
require 'question/document'
その上で、それがQuestion::Document
が定義されています。
このような警告が表示される場合があります
/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
このようない警告は表示されません。
さまざまなクラス定義を順番に配置して、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
require_dependency
ソリューションの代替案を紹介するgemを書きました: heavy_control
constantize
を介して(他の定数がロードされる前に)初期化時に指定された定数名を明示的に解決します。また、開発中にリロードが発生します。