Today I discovered the beauty of $LOAD_PATH in ruby.
Here is the problem:
I created a couple of libraries for an app I’m working on and put them in a ./lib directory and they reference each other like this:
##./lib/lib-a.rb##
require ‘lib-b’
…lib does stuff with classes included in lib-b…
##./lib/lib-b.rb##
require ‘lib-a’
…lib does stuff with classes included in lib-a…
##main.rb##
require ‘./lib/lib-a’
…use lib-a which tries using lib-b…
Well when I’m in the top-level directory and try including one of the libraries it won’t work because lib-a.rb will look for lib-b.rb in the current directory and it doesn’t know to look in ./lib
If I change lib-a.rb to call require ‘./lib/lib-b’ it will work from the main script because it knows how to get to lib-b from the top level directory.
The real problem is that the application is bound by that top level directory now. If I try to make a test in ./tests/test.rb like this:
##./tests/test.rb##
require ‘../lib/lib-a.rb’
The problem is that lib-a is looking for lib-b in ./tests/lib/ because of the ./lib reference….
The basic problem here is that, even though we are using relative paths, the paths are like absolute paths relative to the current directory. We need to avoid such relative paths as much as absolute paths in our code. How do we do this?
The solution:
The ruby require uses the global variable $LOAD_PATH to figure out where to look for libraries. $LOAD_PATH is an array of directories that you can add to to get your libraries loaded properly without any directory spec in the require statement. Here is an example:
##./lib/lib-a.rb##
require ‘lib-b’
##./lib/lib-b.rb##
require ‘lib-a’
##main.rb##
$LOAD_PATH << ‘./lib’
require ‘lib-a’
##./tests/test.rb##
$LOAD_PATH << ‘../lib’
require ‘lib-a’
This will set up the load path to be passed to everything properly so that ruby can just work its magic.
