$LOAD_PATH in Ruby
这篇文章搞定了Ubuntu上的RMagick
$LOAD_PATH /Library/Ruby/Site/1.8
# => /Library/Ruby/Site/1.8/powerpc-darwin9.0
# => /Library/Ruby/Site/1.8/universal-darwin9.0
# => /Library/Ruby/Site
# => /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8
# => /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/powerpc-darwin9.0
# => /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin9.0
# => .
That’s the load path on my OS X system. A bunch of directories, and . (dot). The dot represents the current working directory.
Let’s investigate
# ~/foo/top_level.rb
puts "I rule the world"
require "underlings/slave"
# ~/foo/underlings/slave.rb
puts "I am a slave."
require "equal"
# ~/foo/underlings/equal.rb
puts "I am equal."
Close your eyes. You open a terminal. The current working directory is ~/foo.
$ ~/foo: ruby top_level.rb
I rule the world!
I am a slave.
./underlings/slave.rb:3:in `require': no such file to load -- equal (LoadError)from ./underlings/slave.rb:3
from top_level.rb:3:in `require'
from top_level.rb:3
Ruby looks for equal in the directories in the load path.
~/foo/underlings isn’t in the load path, which means Ruby can’t find equal.rb.
It raises a LoadError.
$ ~/foo: cd underlings
$ ~/foo/underlings: ruby slave.rb
I am a slave.
I am equal.
This time, Ruby finds equal. That’s because the curent working directory is the directory that contains equal.rb, and Ruby adds the current working directory to the load path.
Modifying the load path
Let’s add ~/foo/underlings to the load path.
# ~/foo/top_level.rb
puts "I rule the world"
$LOAD_PATH << "~/foo/underlings"
require "underlings/slave"
Back to the imaginary terminal.
$ ~/foo/underlings: cd .. $ ~/foo: ruby top_level.rb I rule the world! I am a slave. I am equal.
Modifying the load path in a sensible way
# ~/foo/top_level.rb
puts "I rule the world"
$LOAD_PATH << File.join(File.dirname(__FILE__), "underlings")
require "slave"
- File.join is a cross platform file path generator. Platforms vary between using forward and backwards slashes to delimit directories, so you want to do
File.join('foo', 'bar')
, not"foo/bar"
, when referring to directories. - Instead of adding the relative ~/foo/underlings,
File.dirname(__FILE__)
is used. It returns the absolute path to the current file. - Because ~/foo/underlings is in the load path,
require "underlings/slave"
is pointless.require "slave"
instead.
That $: thing
$:
is a shorthand for $LOAD_PATH
. So now you know.
(In fact, $LOAD_PATH
is longhand for $:
. Yeah! Thanks, bryanl.)
Add directories to the beginning of your load path
Speed is some times convenient. If you have a lot of requires to your own load-pathed directories, you might want to add your directory to the beginning of the load path, so that Ruby will look in your own directories before it starts traversing through the system directories.
The load path is an array, Array#unshift to the rescue.
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'foo'))
And there you go.