Requiring code in Ruby
Require or require_relative, that is the question.
TL;DR We can use either require or require_relative and both have their trade offs. Libraries/gems are better off using require and depending on LOAD_PATH, full size applications could use a mixture of both.
Every time I found myself in the need to use require_relative, I had this inner feeling that for some reason I was doing something wrong. But is using require_relative wrong? Is there a better way to load my code?
I decided to spend some time to understand why require_relative exists, and if I should be using it.
Why does require_relative exist?
From ruby 1.9.2 “.” directory was removed from the $LOAD_PATH mainly security reasons and also for the fact that we should not be considering where our code will be run from.
Because of this reason code that previously would that looked like:
Now need to be:
require File.expand_path('../foo', __FILE__)
You might be saying “You silly, you could have just used require ‘./foo’ and get away with it”, well that is not entirely true. The path to be resolve will depend completely from where the the code is executed.
Here a nice example:
│ └── foo.rb
│ ├── class_a.rb
│ └── class_b.rb
Lets assume that lib/foo.rb is:
And that bin/foo.rb:
Now when we execute bin/foo.rb from the fake_gem folder, everything will work, but if we move outside of this folder we will see an error like:
$ ruby fake_gem/bin/foo.rb
/Users/paht_to_gems/kernel_require.rb:54:in `require’: cannot load such file — ./lib/foo (LoadError)
from /Users/path_to_gems/kernel_require.rb:54:in `require’
from fake_gem/bin/foo.rb:1:in `<main>’
It first appeared in ruby 1.9.3 as a replacement for the previous syntax, making it now look like:
require_relative 'foo' # Much less writing, yay!
In a nutshell, this method could be explained as:
The files we reference are relative to the file in which the actual calls are made, rather than the folder in which the script was executed in.
Some discussions over this ruby thread present interesting opinions about the matter at hand. Some people consider require_relative the faster solution since it avoids resolution through $LOAD_PATH.
In the other camp, you can find an interesting point of view were require_relative generates coupling between file structure and the code design.
So, should I use it?
Definitely, maybe. In my experience, if you are developing a library/gem, chances are that the $LOAD_PATH already contains the top folder, so in that case I would recommend to stick with require.
If you find yourself with the need to require a file that is located in a directory on top of your current one AKA “../”, require_relative is best choice.
When developing an application, adding all the main folders that contain ruby code to the $LOAD_PATH can be hard to maintain and so error prone (we could have two files called the same on two different folders). Now in this case we could think about restructuring our code to have a more gem like structure (then making require the best choice) or use require_relative and prevent any resolution conflicts.
I hope this brings a bit more like into the matter and allows a more educated decision in favor of one or the other. There are plenty opinions on this matter, and non of them is right or wrong, but just different ways how we design our code.