From: Brian Candler Date: 2005-07-22T21:48:43+09:00 Subject: Re: Are there packages? > Usually, Ruby projects use the following directory structure: > bin/ # contains Ruby scripts which will be installed > my_program.rb > my_program2.rb > lib/ # contains scripts which contain classes/modules > # they'll be installed into /usr/local/lib/ruby/site_ruby/1.8 > my_program/ > foo.rb # contains, e.g. class MyProgram::Foo > app.rb # contains, e.g. class MyProgram::App > test/ # contains test scripts using Test::Unit > test_foo.rb > test_bar.rb > > bin/my_program.rb could contain code like the following: > require 'my_program/app' > MyProgram::App.new.run Note 1: If you're using modules, which is a good idea to ensure you don't overlap the global namespace, then it's conventional to put the source for Foo::Bar::MyClass in lib/foo/bar/myclass.rb - and therefore the user of this class will pull it in with require 'foo/bar/myclass' Note 2: the "require" filename is tried relative to each of the directories in $LOAD_PATH; and possibly also relative to the current working directory, if $LOAD_PATH contains ".". But it's important to note that it is *not* relative to the location where the file which contains the "require" line is. So, if the code in lib/my_program/app.rb wishes to load the class in lib/my_program/foo.rb, it should contain require 'my_program/foo' and *not* require 'foo' (even though 'foo.rb' is in the same directory as 'app.rb'). Note 3: if you want to run the programs in bin/ without first installing their libraries you can do so, but you'll need to update the $LOAD_PATH appropriately. This can be done by hand: cd bin ruby -I../lib my_program.rb or in the outer directory: ruby -Ilib bin/my_program.rb In programs in the test/ directory, I often put $:.unshift '../lib' as the first line for this purpose ($: is shorthand for $LOAD_PATH). But you still have to run them as cd test ruby test_foo.rb rather than ruby test/test_foo.rb # LoadError: No such file to load -- my_program/foo Again, this is because my_program/foo is tried relative to each of the entries in $LOAD_PATH. We are adding an entry '../lib', which means that '../lib/my_program/foo.rb' will be tried; but this pathname is relative to the current working directory, so you have to 'cd' to a suitable place for it to work. With a bit of work, you can fix this. Something like $:.unshift(File.expand_path(__FILE__+"/../../lib")).uniq! should work regardless of the current working directory: cd /tmp ruby /path/to/test/test_foo.rb # $LOAD_PATH contains /path/to/lib Or, your test program can forcibly set the current working directory to the right place when it starts: Dir.chdir(File.dirname(File.expand_path(__FILE__))) $:.unshift("../lib") If anybody has a simpler solution than this, I'd be interested to see it. Regards, Brian.