I have four models (Document
, Question
, Question::Document
, and Answer
). In my Answer
model I have
validates :text,
presence: { :unless => Proc.new{ |a| a.question.is_a? Question::Document } }
This gives me the the warning
warning: toplevel constant Document referenced by Question::Document
How do I prevent this warning from happening (without renaming my classes)?
Your folder/file structure should look as follows:
app/
models/
question/
document.rb
answer.rb
document.rb
question.rb
And then rails will automatically find the correct models (it will translate the model name to a filename, and namespaces are translated to folders).
Make sure that inside your question/document.rb
the class definition looks as one of the following alternatives:
class Question::Document
end
or
class Question
class Document
end
end
If you write just class Document
you are redefining the toplevel constant Document
.
Note that if the global Document
is defined first, this will also trigger this error. This depends on the code path, so the best way to resolve that, is to add a require_dependency
where needed.
See here and here for more background.
E.g. something like
require_dependency 'question/document'
class Answer < ActiveRecord::Base
end
If you put the file in a different place, where rails cannot automatically find it, you will have to explicitly require it, so rails knows Question::Document
exists.
If for instance, you define Question::Document
inside the Question
model, which is a reasonable place, you will have to explicitly state the dependency to the Question
model in your Answer
model.
So, in that case, in your answer.rb
you will write
require_dependency 'question'
class Answer < ActiveRecord::Base
# ..
end
While plain
require
works, it is preferred to userequire_dependency
instead as it will work with auto-loading, which means: behaves as expected during development.
In Rails, you are not supposed to use "require" as it messes up autoloading.
One solution to this is to append a require_dependency
to the end of the file that defines the outer constant.
app/models/question.rb
class Question
# ...
end
require_dependency 'question/document'
app/models/question/document.rb
class Question
class Document
# ...
end
end
This forces the Question::Document
class to be loaded after the Question
constant is found. Normally, if Rails already knows about the top-level Document
constant, it won't attempt to load Question::Document
if it's not already known.
References:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With