

Ruby’s require method gives you more than enough rope to hang yourself. Having now implemented too many projects with too many different approaches to using require, we thought it was worth writing down the conclusions we’ve come to.
We’ve gleaned most of our knowledge from these two articles, here, and here. So a big thank you to their authors.
Do use requires that are relative to ruby’s load path.
For example,
require 'my_project/b/c'
This assumesthat a directory containing the my_project directory is already in Ruby’s load_path (typically your project’s lib folder). It should be — more on this below.
Don’t use requires that are relative to the file.
For example, avoid:
require File.join(File.dirname(__FILE__), "foo", "bar")
Require decides if a file has already been loaded based on the unexpanded path it’s given. Two different relative paths are treated as two different files, so will be loaded twice. Moreover, it’s just yuky. If I want to figure which file a class is defined in, then I shouldn’t have to navigate a tangled web of file references.
Don’t require rubygems in your code.
It’s rude, not everyone wants to use Rubygems. If you want to use it then run
ruby -rubygems my_file.rb
OR use the following environment variable
RUBYOPT="rubygems"
Don’t manipulate ruby’s load path in your code.
Gem will always add your project’s lib directory to ruby’s load path. However, if your running an executable directly from your project (i.e. in your bin directory), or you’re running a set of units tests, then you’ll need to add your lib folder to ruby’s load path. There are a few ways to do this:
Add this line to the top of your executable (contradicts what I just said, but at least in a consistent way).
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib') unless $LOAD_PATH.include?(File.dirname(__FILE__) + '/../lib')
Or run Ruby like this:
Ruby -Ilib my_test_runner
Or set this shell environment variable:
export RUBYOPT=Ilib
Do use underscores as a separator in your project’s name.
No spaces, dashes, or camel case. Most ruby gems follow this convention, so best not to surprise people.
Do create a sub-directory under /lib with the same name as your project. And stick all your ruby files under this.
This is important if you want to package your project up as a Gem at some stage. The contents of every gem’s lib directory installed on your system automatically gets included in ruby’s $LOAD_PATH. Sticking all your code files directly in your lib is asking for same filename collisions. Even if you’re not going to package your project as a gem, it pays to follow this rule for consistency reasons.
Do create a file within your lib directory that is responsible for requiring in your other project files.
This is really an extension of the above. If you’ve nested all your code files in a project directory, then you need a single code file that is responsible for loading them all. For example, your lib fold should look like:
lib/my_project.rb
lib/my_project/
Do make your class namespaces correspond to your directory structure.
Your classes should be within modules that match the directory structure. This way you’re keeping your code namespace consistant with your directory namespace, making it easier to find things. For example, any ruby files in foo/bar should also be in a module Foo::Bar. More importantly, you’re reducing the risk of namespace collision from other libraries.
Do stick your executables in /bin. This is the default location where Gem will install executables from. You can change it, but you shouldn’t unless you have a good reason to.
Don’t use a suffix on your executables (i.e. no .rb). If you’re providing an executable to be run from the shell, then it should work like any other executable (i.e not have a .rb appended at the end).
Do use the following shebang line at the top of your ruby code to make it into an executable.
#!/usr/bin/env ruby
If the above were boiled down to a single principle, it would be this:
Treat require like it’s requiring a namespace, and not a file. This is much the same as how import, and using, work in languages such as >C#, C++, and Java.
© 2010 - VisFleet Ltd
No prawns were harmed in
the making of this website
Comments