From: Stefano Crocco Date: 2008-10-08T04:50:35+09:00 Subject: Re: load vs require Alle Tuesday 07 October 2008, Patrick Doyle ha scritto: > I started looking through the source code for rake and noticed something > curious. > > I see that when I execute the "rake" command at the command prompt, I run a > fairly trivial ruby script: > > require 'rubygems' > > version = ">= 0" > > if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then > version = $1 > ARGV.shift > end > > gem 'rake', version > load 'rake' > > The #gem method prepended "..../gems/rake-0.8.3/bin" and > ".../gems/rake-0.8.3/lib" to my $LOAD_PATH (the "bin" directory first). > Thus, when the script invokes the #load method, it grabs > "..../gems/rake-0.8.3/bin/rake" and starts to execute it. It looks like > this: > > begin > require 'rake' > rescue LoadError > require 'rubygems' > require 'rake' > end > Rake.application.run > > Somehow, the "#require" method knows that it should load the "rake.rb" file > from the "lib" directory (the second element in $LOAD_PATH) instead of the > already loaded "rake" from the "bin" directory, (the fist element in > $LOAD_PATH). > > Why is that? > > --wpd According to the ri documentation for require, if you pass it a filename which doesn't have extension .rb or .so (or .dll or .o, depending on your system), then require tries to add those extensions to the file name and to load the corresponding library. So, the code require 'rake' will cause ruby to look for one of the files rake.rb or rake.so in the directories listed in $:. The script in bin is called simply rake, not rake.rb, and so require doesn't even consider it. load, instead, interpret its argument in a different way: it considers it to be the whole basename of the file and doesn't try to add any extension to it. So, the line load 'rake' will make ruby look for a file called 'rake' (not rake.rb as before) in the directories listed in $:. This time bin/rake has the correct name and is loaded. You can see it yourself by doing the following: * create a file with a name which doesn't end in .rb, for example test_load_require, then put some ruby code in it. Start irb in the same directory of the file and issue the command require 'test_load_require' ruby will complain (raising a LoadError) because it can't find the file. Now call load 'test_load_require' and you'll see that the file is correctly loaded and the code in it is executed. I hope this helps Stefano