Let's say I have a gem called foo, with a file structure like so:
task :build do
`gem build foo.gemspec`
`gem uninstall foo`
`gem install ./foo-0.0.0.gem`
It's error-prone and confusing having to mess with
require paths within your source files in order to make the code run in different situations (local testing, "production" as a gem etc.).
There are some tricks you can use to "write once, run anywhere" (sorry Java, for stealing). This is also what you should aim for, using these standard practices makes it easier for others to understand your code or help you out if something doesn't work as expected.
Your code already follows the common gem directory layout, nothing needs to be changed there. But, as a general rule of thumb, you should use
require to load "libraries" and
require_relative (if you are on Ruby >1.9) to load source files relative to the one you are working on.
1) Your file test_foo.rb should only contain a line:
That is you omit the './lib' part from the require path. The entry point for the gem (the "require_path") is commonly chosen to be "lib". More on that later (3).
2) Next, in foo.rb, use
require_relative (again assuming Ruby 1.9) to pull in the relative source files:
require_relative 'foo/file1' require_relative 'foo/file2'
3) To set the require_path to lib for your gem, it's considered good practice to add a gemspec file.
To test your code (for example with your test_foo.rb), you have several options:
4) You can run test_foo.rb with ruby's
-I option to include the lib/ directory in its load path:
ruby -I lib test_foo.rb
This is much less obtrusive than adding additional includes directly in your code.
5) Bundler is an even better way to manage your code/gem in order to test it under "real-life" conditions, especially if you develop two or more gems at once that rely on each other. Bundler gives you the option to reference these gems locally, so there's no need to deploy them formally in order to test their functionality during development. To use Bundler, you would add a Gemfile to the root directory of your gem code.
6) Finally, for convenience, it makes sense to integrate common steps in your development process into a Rakefile, using rake to drive the processes.
I use these techniques quite a bit in my own projects, here are some links for your reference to give you some concrete examples:
Of course you don't need to use all of these techniques, you'll probably be fine with using steps 1-4, but as your project grows larger, the additional effort will definitely pay off.