24

Is there a way to force require-ing of a file for the second time?

I am writing a library that is located in a path for Ruby. I am editing the file while doing a simple test of it in IRB.

Each time I make a change to the file, I want to reload it without ending the IRB session. Using load requires typing the whole path to the file each time, and restarting IRB each time requires me to type all the other variable settings required for the simple test.

I just want something like require but that allows loading for the second time. Is there a simple way to do it?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
sawa
  • 165,429
  • 45
  • 277
  • 381

3 Answers3

32

load does not require (hmm) a full path. It expects a complete filename with an extension.

p load 'date.rb' #=> true
p load 'date.rb' #=> true
p load 'date'    #=> LoadError
steenslag
  • 79,051
  • 16
  • 138
  • 171
  • I knew about the difference between whether or not having ".rb", but somehow I didn't realize about the path. – sawa Apr 25 '12 at 02:20
4
:000> path = "extremely/long/path/to/my/file"
:001> load path
:002> load path
Francisco Soto
  • 10,277
  • 2
  • 37
  • 46
4

You could write your own and put it in your .irbrc:

New Hotness

module Kernel
  def reload(lib)
    if old = $LOADED_FEATURES.find{|path| path=~/#{Regexp.escape lib}(\.rb)?\z/ }
      load old
    else
      require lib
    end
  end
end

Minutes-Old and Therefore Busted

module Kernel
  # Untested
  def reload(lib)
    if File.exist?(lib)
      load lib
    else
      lib = "#{lib}.rb" unless File.extname(lib)=='.rb'
      $:.each do |dir|
        path = File.join(dir,lib)
        return load(path) if File.exist?(path)
      end
    end
  end
end

For the old-and-busted version you would have to make it more robust if you wanted to support RubyGems.

One problem with either of these solutions is that while it will force-reload the file in question, if that file in turn calls require on others (as is usually the case with gems) those files will not be reloaded.

Working around this would be really ugly. Like, maybe manually reaching into the $LOADED_FEATURES array and ripping out all the paths that looked to be related to the gem's name. shudder

Phrogz
  • 296,393
  • 112
  • 651
  • 745
  • I've edited the answer to include a simpler version taking advantage of existing require magic. – Phrogz Apr 24 '12 at 22:44
  • Thanks for the help. Actually, my question may have been stupid. As steenslag answers, I might not have to have worried about the path after all. But your code will be useful. – sawa Apr 25 '12 at 02:19