![]() |
Articles Feed |
Categories
Archives
- July 2010 (5)
- June 2010 (4)
- April 2010 (3)
- March 2010 (2)
- February 2010 (2)
- January 2010 (1)
- December 2009 (1)
- October 2009 (2)
- September 2009 (2)
- August 2009 (1)
- July 2009 (5)
- June 2009 (2)
- May 2009 (2)
- April 2009 (8)
- March 2009 (7)
- January 2009 (2)
- December 2008 (3)
- November 2008 (5)
- October 2008 (4)
- September 2008 (6)
- August 2008 (4)
- July 2008 (5)
- June 2008 (5)
- May 2008 (4)
- April 2008 (2)
- February 2008 (4)
- January 2008 (2)
- December 2007 (2)
- November 2007 (2)
- October 2007 (2)
- September 2007 (1)
- August 2007 (3)
- July 2007 (1)
- June 2007 (4)
- May 2007 (7)
- April 2007 (2)
- February 2007 (3)
- January 2007 (3)
- November 2006 (3)
- October 2006 (3)
- September 2006 (17)
- November 2004 (1)
Micah's General Guidelines on Ruby require
by: micah | October 8th, 2007 |
Ruby files have to require other files. There’s not avoiding it. Techniques to manage require statements are numerous and varied. Having tried most of them, I’ve found a system that works well for me. What follows are the guidelines I use to manage Ruby require statements.
1. Establish a Convenient Search Path
Although it’s possible to use absolute paths or complex relative paths such as below,
- require "/Users/micahmartin/Projects/ttt/lib/game"
- require File.dirname(__FILE__) + "../../../lib/ai/winner"
this should be avoided as much as possible. Otherwise you’ll be fixing dozens of require statements every time you move a file. It’s no fun. You’ll want your requires to look like this:
- require "game"
- require "ai/winner"
To achieve this, add your lib directory to the ruby search path.
$: << File.expand_path(File.dirname(FILE) + “/../lib”))
This will have to go in one of the first files that gets loaded. If you’ve got a standalone Ruby app, you could add this to the startup script. In a Rails app, it can go in environment.rb. If you’re using RSpec, you may want to add it to spec_helper.rb.
2. Independent Requiring over Require Farms
In some projects, you’ll find files that contain nothing but require statements. It’s common in gem projects. The advantage is that users of the library need only require one file which in turn requires everything else you’ll need. Convenient huh? Sure is. But there are 2 major consequences of this:
- Maintenance Mayhem - Every time you add, delete, or rename a file you have to remember to update the require farm file. It’s easy to forget. And the order of requires can get very hard to manage especially if you end up with cyclic dependancies.
- Drowning in Dependancies - Require Farms have a tendency to require more than you want. If there’s only a portion of the library you’d like to use, with the Require Farm you get the whole thing. The extra dependancies will consume more memory at run time and they may add undesired behavior to your system. In general, this is a violation of the Dependancy Inversion Principle.
Rather than build Require Farms, allow each file to be responsible for it’s own dependancies. Let each file require the files it needs to work. This approach can be a bit annoying as you’ll find your self using altogether more require statements, but it’ll pay off in the long run. With each file independently managing it’s dependancies, the system will be easier to maintain and it’s components more reusable.
3. Building Absolute Paths
Try as you may, you can’t always avoid using absolute file paths in your require statements. The following is reliable way to refer to other files.
- File.join(File.expand_path(File.dirname(__FILE__)), "..", "spec_helper")
Let me break it down. First:
- File.dirname(__FILE__)
This gives you the directory of the current file that is being executed. However, you never know what you’re gonna get since the form of the path is based on how the program was executed. This might give you an absolute path or it might give you a relative path from anywhere on the system. In some cases, Ruby won’t do what you expect with relative paths so it’s best to expand this into an absolute path.
- File.expand_path(File.dirname(__FILE__)
Now you’ve got an absolute file path and you just have to add a relative path to the desired file. Normally I’d do this:
- File.expand_path(File.dirname(__FILE__) + "../spec_helper")
However, this is not quite portable since I’m using forward slashes. To get this to work on any system independent of file separator, use File.join as shown above. Use this technique to require files when you don’t have your search path configured.
Happy Requiring!

October 18th, 2008 at 06:32 PM fine little stuff always helps. thanks !
October 18th, 2008 at 06:32 PM thanks from a ruby noob for the very useful information
October 18th, 2008 at 06:32 PM a thorough explanation, which is rare. you're right, the cyclic dependency issue is non-trivial. compilers need to be expanded to handle cyclic refs, redundancy, ordering, etc. just like installation software has done for years (and screwed up for years i might add).
October 18th, 2008 at 06:32 PM Correct me if I am wrong but I believe ruby will use either a forward slash or a backslash regardless of operating system. So the File.join is not strictly necessary to make it cross platform.
October 18th, 2008 at 06:32 PM Let's just all agree that the default is "Correct me if I am wrong", so there would be no need to preface statements with this kind of qualifier unless you mean "Do NOT correct me if I am wrong". Wouldn't that save a lot of wasted bandwidth? Trust me - if you are wrong, someone will correct you. You don't have to give permission.
October 18th, 2008 at 06:32 PM Steve: As far as I can tell you are correct though feel free to correct me if I am wrong. Eric Anderson: ri File.join
October 18th, 2008 at 06:32 PM Thanks for the post, it helped a lot.
November 22nd, 2008 at 04:21 PM
$: << File.expand_path(File.dirname(FILE) + “/../lib”))
should read
$: << File.expand_path(File.dirname(FILE) + “/../lib”))
no?
January 16th, 2009 at 05:50 PM
Thanks for this! As unglamorous as it is, it is very important, and yet I couldn't find this basic info on how to properly structure my load paths anywhere! Thanks!
January 20th, 2009 at 04:25 AM
@snash, sadly your correct fell at the same hurdle as the original example. To avoid falling at it too, I think what you're trying to say is that there should be a double underscore before and after the word 'FILE'.
February 15th, 2009 at 07:19 AM
thank you for giving us these advices. I will use them in my work. You're right, the cyclic dependency issue is non-trivial. compilers need to be expanded to handle cyclic refs, redundancy, ordering, etc. just like installation software has done for years (and screwed up for years i might add).
March 7th, 2009 at 03:34 PM
Thanks mate! Exactly what I needed.
August 13th, 2009 at 12:46 AM
"Rather than build Require Farms, allow each file to be responsible for it’s own dependancies. Let each file require the files it needs to work. This approach can be a bit annoying as you’ll find your self using altogether more require statements, but it’ll pay off in the long run. With each file independently managing it’s dependancies, the system will be easier to maintain and it’s components more reusable."
All of the above "it's" should be "its".
November 28th, 2009 at 03:17 PM
shouldn't it be "dependEncy" instead of "dependAncy"?