Posted: June 4, 2011. Tags: Rails
In development mode, Rails will reload all classes you use for each request, allowing you to rapidly modify and test code without restarting the server. Recently, while debugging a gem I was developing, I had cause to figure out how this all works.
For reloading of a class or module to work, there must not be a constant defined at the start of the request matching that class/module. This is because Rails uses const_missing to detect undefined constants and then try to satisfy the reference. This means reloading will not work for anything that has already been included at application boot time, which includes all gems.
When ActiveSupport::Dependencies
is loaded, ActiveSupport::Dependencies.hook!
includes ActiveSupport::Dependencies::ModuleConstMissing
into Module
, which contains a #const_missing
method.
#const_missing
loops through the current namespace and then each of its ancestors in turn, calling #load_missing_constant
for that namespace and the desired constant.
#load_missing_constant
converts the constant to a file pathname suffix (e.g. Foo::Bar -> "foo/bar") then attempts to find that file (#search_for_file
) in each of the folders listed in array autoload_paths
(which can be modified in config/application.rb).
If it finds a file, it loads it (see #load_file
& #autoload_module!
) and remembers the filename in variable loaded
so it doesn't do it twice.
If loading the file successfully defined the constant, it gets remembered in array autoloaded_constants
.
After each request, Rails unloads all constants that were defined using the above method. Rails::Application::Bootstrap
sets up ActionDispatch::Callbacks.after
to call ActiveSupport::Dependencies.clear
.