Since I finally found a use for the Rails metal applications (basically, Rack applications run before going through regular routes), I was surprised for my code not to be reloaded between requests in development mode. This article presents a portable monkey patch that implements this missing behaviour.
Problems
As mentioned in the introduction, metal applications precede the regular request dispatch. But since constants are reloaded just before this dispatch happens, constants are still old at the time metal applications are cascaded through.
Not only that, but Rails::Rack::Metal uses require to load metal application constants instead of letting ActiveSupport::Dependencies handle them like models, controllers and such. And since the Rails initializer attempts to load any existing metal application to determine whether it’s worth adding the Metal middleware to the stack or not, the corresponding constants are initially loaded via require, making them unknown to AS::Dependencies, thus preventing them from being reloaded afterward.
Patch
The patch below circumvents the above problems by:
reverting the consequences of the calls to
requirefromMetal.metals, and preventing furtherrequire’s from happening;adding a new step before going through the metal application stack which consists in forcing all constants to be reloaded and rebuilding the list of available metal applications from fresh constants.
Tuck the following chunk of code in config/initializers/reload_metals.rb:
(If the code doesn’t show up, get the gist manually.)
Or place it inside config/environments/development.rb, wrapped in a config.after_initialize do .. end block, and stripped from the bottom if Rails.env.development? statement.
Caveats
The above patch hasn’t been tested extensively, so use at your own risk. Nothing critical could happen though: I haven’t noticed anything strange yet, but at worst, expect weird constant (re)loading behaviour.
With this patch applied, constants are reloaded twice if the request goes past the metal application stack: once before the stack, and once before the normal dispatch. This can slow down development mode if you have a lot of models. Ideally,
ActionController::Dispatcher#reload_applicationand#cleanup_application(for Rails up to 2.3.0) should be inhibited if both theMetalmiddleware and the patch of this article are active.
Compatibility
The patch doesn’t seem to be compatible with edge Rails (> 2.3.2.1) anymore. I won’t look into it for now since I don’t use it anymore but any contribution towards making it compatible with the latest version of Rails would be welcome.
Updates
UPDATED 2009-04-13: Added a note about compatibility.


