From: Joel VanderWerf Date: 2008-04-16T01:07:23+09:00 Subject: Re: How to reliably setup require path Eric Hodel wrote: > 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.) It depends. The -I solution won't help with: - making your app double-clickable (or hash-bang executable from the command line) - locating other resources, like myapp/icons. - stting up the same access (to lib and other resources) for ruby processes fired off by system, popen, etc. -- vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407