From: Eric Hodel Date: 2008-04-15T18:21:44+09:00 Subject: Re: How to reliably setup require path On Apr 14, 2008, at 16:16 PM, Joel VanderWerf wrote: > Christian Johansen wrote: >> I'm writing my first Ruby command line application (beyond a simple >> script) and I'm little unsure about how to structure the >> application and >> the best use of require. I've come as far as to have the following >> file >> structure: >> myapp/ >> bin/ >> myapp >> docs/ (RDOC files) >> lib/ >> myapp.rb >> myapp/ >> files and folders here >> test/ (Test::Unit tests) >> And the application is working, but there are a few things of which >> I am >> unsure: >> The bin/myapp file is a symlink to the lib/myapp.rb file which has a >> shebang line. This doesn't really work, because inside lib/myapp.rb I >> have: >> require 'myapp/file' >> require 'myapp/module/file' >> which doesn't make sense when running the application from anywhere >> else >> than myapp/lib >> I also tried >> $MYAPP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), >> 'myapp')) >> $LOAD_PATH << File.expand_path($MYAPP_ROOT) >> Which still doesn't work because this also relies on cwd... >> How do I work around this? What's the best practice way of making >> these >> things make sense? Do you use the $RUBYLIB variable to set the full >> path >> to the application? I was hoping to create the application as >> standalone >> as possible, so installation will be easy. > > > I'd do a couple of things differently (and I've used this pattern in > a number of applications with the same dir structure as yours): > > 1. make bin/myapp a very short ruby script instead of a symlink (if > you want this to work on windows, symlinks won't work anyway). > > 2. use unshift instead of <<, so you get precedence > > 3. use an ENV var instead of a global so child scripts can use it > > 4. use File.dirname to go up two levels instead of one, so that you > can use it to find non-lib files as well (images for example, or > other data files). Note that the expand_path call has to happen > before calling dirname twice. > > Here's the code: > > ENV['MYAPP_BASE'] = > File.dirname(File.dirname(File.expand_path(__FILE__))) > libdir = File.join(ENV['MYAPP_BASE'], "lib") > $LOAD_PATH.unshift libdir > ENV['RUBYLIB'] = libdir + ":" + ENV['RUBYLIB'] The simplest way is `ruby -Ilib bin/myapp` from the root of the project dir. (-I directories take precedence over RUBYLIB directories.)