Rails snippet: require app files only once

16 05 2008

Ruby’s Kernel.require method will re-require the same source file if you pass it differing arguments that point to the same file. It doesn’t use File.expand_path to make sure it hasn’t already loaded the same file before. This can cause problems if you’re using constants or doing one-time initialization in a source file that’s getting loaded multiple times for one reason; you’ll need to add a wrapper that prevents re-entry.

If this annoys you as much as it does me (why should my application code include workarounds for what I regard to be a Ruby bug?), add this snippet to your config/environment.rb (pre Rails 2.0) or config/preinitializer.rb (Rails 2.0 or later).

module Kernel
    def require_with_expand_path(source_file)
        expanded = File.expand_path(source_file)
        is_app_file = File.file?(expanded)
        require_without_expand_path(is_app_file ? expanded : source_file)
    end
    alias_method 'require_without_expand_path', 'require'
    alias_method 'require', 'require_with_expand_path'
end

The is_app_file check may not be the best way to test for it; I can see how if you fiddle with $: so that the current directory files load after some other directory, you might load things in the wrong order. Please post fixes if you find this to be a real problem and have an idea of how to fix it.


Actions

Informations

2 responses to “Rails snippet: require app files only once”

16 05 2008
Making Rcov measure your whole Rails app, even if tests miss entire source files at Pervasive Code (16:42:44) :

[...] of all this require-ing, you might want to apply the snippet in my prior post, which eliminates duplicate required source files if they’re under your RAILS_ROOT. Otherwise [...]

20 02 2009
roger (18:23:23) :

This fails if you require ‘filename’ and ‘filename.rb’ and also doesn’t expand the path fully if it was found in library directories, etc.
Here’s my hack at it:
http://github.com/rogerdpack/roger-useful/tree/a3c4867cd3eef0f6f088e88f1218184cb21a6803/unique_require
Cheers!
-=r

Leave a comment

You can use these tags : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>