Rails developers know that in development mode classes are loaded on demand. In production mode all the classes are loaded as part of bootstrapping the system. Also in development mode classes are reloaded every single time page is refreshed.
In order to reload the class, Rails first has to
unload . That unloading is done something like this.
However a class might have other constants and they need to be unloaded too. Before you unload those constants you need to know all the constants that are defined in the class that is being loaded. Long story short rails keep track of every single constant that is loaded when it loads
Dependency mechanism is not perfect
Sometimes dependency mechanism by rails lets a few things fall through the crack. Try following case.
Start the server in development mode and visit
http://localhost:3000/users . First time every thing will come up fine. Now refresh the page. This time you should get an exception
uninitialized constant OpenURI .
So what’s going on.
After the page is served the very first time then at the end of response rails will unload all the constants that were autoloaded including
UsersController. However while unloading
UsersContorller rails will also unload
When the page is refreshed then
UsersController will be loaded and
require 'open-uri' will be called. However that require will return
Why require returns false
Try the following test case in irb.
step 3 : ensure that OpenStruct is truly removed
Notice that in the above case in step 4 require returns
false. ‘require’ checks against
OpenStruct was removed then it was not removed from
$LOADED_FEATURES and hence ruby thought
ostruct is already loaded.
How to get around to this issue.
require loads only once. However
load loads every single time. In stead of ‘require’, ‘load’ could be used in this case.
Back to the original problem
In our rails application refresh of the page is failing. To get around to that issue use
require_dependency instead of
require_dependency is a rails thing. Under the hood rails does the same trick we did in the previous step. Rails calls
kernel.load to load the constants that would fail if require were used.