Friday, August 11, 2006

Reloading Revamped

Posted by nicholas

A few days ago I checked in a significant improvement to Rails’ dependencies and reloading code. In the past, changes to dependencies.rb have shed the blood of those courageous enough to ride edge; We’ve worked hard to prevent accidental breakage this time, but there may be some changes that could break your app.

Before you freeze edge to the prior revision, I should explain that most breakage will be extremely simple to fix. Prior to this revision, Rails would happily load files from Ruby’s standard lib via const_missing; you will now need to explicitly require such files. (Rails’ autoloading was intended as a replacement for require_dependency; its replacement of Ruby’s require is unfortunate and undesired.)

This change is not the only one that has occurred. Rails’ Reloadable module has been deprecated, and the previously independent systems of automatic loading and unloading have been brought together in a happy union.

Dependencies’ new behavior should be more reliable and less annoying. Annoyances such as the lack of module reloading have been fixed. Accidentally loading stdlib packages will no longer occur.

The actual mechanics of Dependencies are now relatively simple. Instead of using Reloadable to decide which classes to unload, Rails records which constants are loaded via const_missing. When the request is completed, each autoloaded constant is removed, leaving the process in a clean state. The actual mechanics are slightly more complex, but not inordinately so. Feel free to open dependencies.rb and peruse the code.

Hopefully the newfound simplicity of this approach will improve the transparency of Dependencies — some software is best when not noticed. If you’re running on trunk this change does cause your application to error, please do open and assign Ulysses a ticket.

Before I depart, I’d like to mention another (independent) change to dependencies: When Rails fails to find a missing constant, you will now see a fully qualified constant name in the description. For example, if a method in your User class references Acount, (rather than Account,) Rails will state that User::Acount is missing rather than ::Acount. Rest assured that Rails has looked for Acount in Object as well as User, and is merely reporting the fully qualified constant name, as Ruby’s own const_missing does.