Rails: organizing models in subfolders having warning: toplevel constant A referenced by B::A
Update: This years Christmas present was the release of Ruby 2.5.0 with which this error won't happen anymore. With Ruby 2.5+ you will either get the constant you asked for or an error. For older Ruby versions read on:
Your User::File
class is not loaded. You have to require it (e.g. in user.rb
).
The following happens when ruby/rails sees User::Info
and evaluates it (simplified; only User
is defined yet).
- check if
User::Info
is defined - it is not (yet) - check if
Info
is defined - it is not (yet) uninitialized constant
-> do rails magic to find theuser/info.rb
file and require it- return
User::Info
Now lets do it again for User::File
- check if
User::File
is defined - it is not (yet) - check if
File
is defined - it is (because ruby has a built inFile
class)! - produce a warning, because we've been asked for
User::File
but got::File
- return
::File
We observe that the rails magic, that automatically requires files for (yet) unknown constants, does not work for User::File
because File
is not unknown.
Preventing warning: toplevel constant B referenced by A::B with namespaced classes in Rails
I solved this issue by using a require statement in an initializer. I don't like it much but I liked the structure and class names of my application, they made sense so an initializer was my best solution. In the initializer try:
require File.join(Rails.root, "app", "presenters", "mega_menu", "catalog_presenter")
require File.join(Rails.root, "app", "presenters", "catalog_presenter")
This problem occurs because autoload relies on const_missing being called which won't happen in your case.
When ruby first encounters a reference to MegaMenu::CatalogPresenter, the mega_menu/catalog_presenter.rb file has not been included. Standard ruby behaviour causes it walks up the namespace tree (figure of speech) and it instead finds the top level reference CatalogPresenter as this HAS been included at this point.
Best way to separate Sequel model definitions into different file?
Of course it's possible. Extract the definitions into their own file (say, models.rb
), and put require_relative('models')
where they used to be.
Or you can even put each model in its own file in a directory, say models/person.rb
..., and then
Dir["models/*.rb"].each { |file| require_relative(file) }
Showing a warning message when before_create fails?
A before_create
isn't the right place to be reporting errors. Your before_create
should try to set the value and then a validator should check if it is there, if the validator doesn't find the value then you'll get your error message and such. So, if your attribute is called pancakes
, then you'd have something like this:
before_validation :stuff_web_api_value_into_pancakes, :if => :new_record?
validates_presence_of :pancakes
You could, of course, use a different validator than validates_presence_of
, that's just there for illustrative purposes. And you'll want a before_validation
hook to get things to happen in the right order, the :if => :new_record?
will only run the hook when you're creating a new model.
Related Topics
How to Send Custom Invitation Using Devise_Invitable
Confused with Ruby Accessor Methods
Gmaps4Rails:Setting Map Width and Height
Why Is Ruby's Loop Command Slower Than While True
Bundler: Not Executable: Script/Delayed_Job
Enforce File Upload Size on Heroku
Pass Arguments by Reference to a Block with the Splat Operator
Heroku: Error Pushing Rails App to Heroku, Heroku Can't Find Rails App
Convert String Numbers( in Word Format) to Integer Ruby
Rails 4 Not Encrypting Cookie Contents
-Bash: /Usr/Local/Bin/Heroku: /Usr/Local/Bin/Ruby: Bad Interpreter: No Such File or Directory
Currying a Proc with Keyword Arguments in Ruby
Ruby on Rails - Add Condition on ':Include =>' to Load Limited Number of Objects
Differencebetween a Constant and a Variable in Ruby
Rewrite Template.Js.Erb into Template.Js.Slim
How to Pass the JavaScript Value as JSON Object to the Controller in Ruby on Rails