“Object is not missing constant XXX” and “A copy of YYY has been removed from the module tree but is still active” when using Rails metal
If you have a Rails metals that has enough code to have it’s own
subdirectories that live in your Rails load_paths you can get stuck in
dependency hell. The combinations of autoloading, rails reloading on
development, and running through the metal can intersect in nasty
ways: on the first request you get “Object is not missing constant
XXX” and subsequent requests kick off “A copy of YYY has been removed
from the module tree but is still active.” The easiest solution is to kill magic reloading for this metal’s code;
add the metal’s directories of code to the Rails load_once_paths and
then use explicit require_dependency calls for any files that give you
trouble. For example, I have a MadMetal that referenced a Mad which
has a whole sub-directory structure of code that, for now, lives under
lib/mad:
lib/mad. In this case it’s not a problem for me because the app is
also a stand-alone rack app that I run with shotgun when I want development environment reloading.
subdirectories that live in your Rails load_paths you can get stuck in
dependency hell. The combinations of autoloading, rails reloading on
development, and running through the metal can intersect in nasty
ways: on the first request you get “Object is not missing constant
XXX” and subsequent requests kick off “A copy of YYY has been removed
from the module tree but is still active.” The easiest solution is to kill magic reloading for this metal’s code;
add the metal’s directories of code to the Rails load_once_paths and
then use explicit require_dependency calls for any files that give you
trouble. For example, I have a MadMetal that referenced a Mad which
has a whole sub-directory structure of code that, for now, lives under
lib/mad:
#environment.rb
config.load_paths += Dir["#{RAILS_ROOT}/lib/mad/**/"]" #app/metal/mad_metal.rb
require_dependency 'mad'
class MadMetal
def self.call(env)
if (env["PATH_INFO"] == '/mad/')
Mad.call(env)
else
[404, {"Content-Type" => "text/html"}, ["Not Found"]]
end
end
end
And wallah, no more conflicts between development auto-reloading and metal. Of course, now you need to restart the server if you change code in lib/mad. In this case it’s not a problem for me because the app is
also a stand-alone rack app that I run with shotgun when I want development environment reloading.