How Rails Class Reloading Works

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.