Ruby provides a few different ways to load another Ruby program or external library. You can load
it, autoload
it, require
it, or require it relative to the current directory using require_relative
. Although they look and sound quite similar, there're a few important differences between them that can be confusing to understand.
After a year and a half of programming in Ruby, I still didn't quite understand all the nuances and differences between these methods. So after a few hours of study last night, here's everything I learned about loading external Ruby scripts in your programs. This post explains how they differ from each other and when you should use each. I hope you find this information helpful.
TL;DR: Use load
to pick up any changes you made to a file while the program is running. Use autoload
to speed up the initialization of your library by lazily loading the modules. Use require
when you want to use external gems. Use require_relative
for local files relative to the current working directory.
Let's dig deeper.
The 'load' Method
The load method takes the filename
as input. When the Ruby interpreter comes across the load
method, it will load and execute the Ruby program in the file filename
. If it comes across it again, it will load and execute it again, picking any new changes in the file.
Thefilename
can be either an absolute path or a relative path using.
or..
, and Ruby will load and run that Ruby file. If it can't find the file, Ruby will search for it in the directories listed in $LOAD_PATH variable.
Let's create two Ruby files (in the same directory) with the following code.
# script.rb
puts "Inside script"
load "loaded_script.rb"
puts "Inside script"
load "loaded_script.rb"
# loaded_script.rb
puts "Loaded file"
Running the first script gives the following output.
~ ruby script.rb
Inside script
Loaded file
Inside script
Loaded file
Notice that each call to the load
method executes the loaded script. Hence the output Loaded file
was printed twice.
A call to the load
method always loads that file. It doesn't matter if you had already loaded it earlier.
If you load a file, make a change to that file, and load it again, load
will pick your new changes, which will override the original contents of the file. This is useful for making changes when a program is running and examining them immediately without reloading the application.
Remember: load
will run the code every time, so if you are loading a Ruby script in multiple locations, you're doing lots of unnecessary work.
The 'autoload' method
This method takes two arguments: a module (it can be either a string or a symbol) and a filename (string), and registers the filename to be loaded the first time that module is accessed.
autoload(:TestModule, "lib/modules/test_module.rb")
Using autoload
allows you to speed up the initialization of your library by lazily loading the modules that your code depends on. It won't load the library or framework code you aren't using.
# script.rb
puts "Inside script"
autoload :LoadedScript, "./loaded_script.rb"
puts "Inside script"
LoadedScript.new
# loaded_script.rb
puts "Loaded file"
class LoadedScript
end
Running the first script outputs the following:
~ ruby script.rb
Inside script
Inside script
Loaded file
Note that the loaded_script
was executed only when I created an instance of LoadedScript
, not when I autoloaded it.
Additionally, Ruby on Rails overrides Ruby's autoload
method to use Rails' naming conventions, which lets you skip the second argument, i.e. the filename. To learn more about it, check out the following article.
The 'require' method
The require
method also loads the given file, similar load
. However, it won't load the file if it's already loaded. Any constants, classes, modules, or global variables within the required file will be available to the calling program.
If the filename neither resolves to an absolute path nor starts with./
or../
, the file will be searched for in the library directories listed in$LOAD_PATH
.
Requiring a library a second time won't execute it again.
# script.rb
puts "Inside script"
require "./required_script"
puts "Inside script"
require "./required_script"
# required_script.rb
puts "Required file"
Running script.rb
provides the following output.
Inside script
Required file
Inside script
Note that requiring the script again didn't execute it, unlike the load
method. Also, the file extension .rb
is optional in require
, whereas load
will loudly complain about it and crash. Β
When using require
, you can use the ./
format for a file in the current directory, e.g. require "./script"
. However, it's not a common practice. Instead, you should use the require_relative
method. Reserve require
for loading the external gems.
Use require
for loading Ruby gems
When yourequire
a gem, really youβre just placing that gemβslib
directory onto your$LOAD_PATH
.
The require
method uses the $LOAD_PATH
to locate the mentioned file. As the Ruby gems are installed in a directory present in $LOAD_PATH
, this allows you to require them without providing the path.
require 'minitest'
Once you've required minitest
, RubyGems automatically places its lib
directory on the $LOAD_PATH
.
That's how Ruby gems work. You write the gem's Ruby code into the lib
directory containing a Ruby file with the same as your gem. For the minitest
gem, the file will be minitest.rb
. Additionally, the lib
directory contains a directory with the same name as the gem containing the rest of the files.
% tree minitest/
minitest/
βββ lib/
βββ minitest/
β βββ code.rb
β βββ app.rb
β βββ ...
βββ minitest.rb
Since the lib
directory is placed into $LOAD_PATH
, you can require the gem without providing the path. Ruby will know where to load it from.
The 'require_relative' method
In the previous example, we provided the path to the required file as ./required_script
, that is, using the .
to indicate the current directory. The require_relative
method loads the external file by searching relative to the file from which it's called. This allows you to write:
require_relative "required_script"
The code will result in the same output as require
; they work in the same way.
require_relative
is useful when you want to navigate the local directory hierarchy as follows:
require_relative "lib/rails/server"
Use require_relative
for local files relative to the current working directory.
Confused?
At this point, you might be really confused about the exact difference between require
and require_relative
. It feels like they both are doing the same thing. I was confused, too. So I did some further digging and came across this excellent StackOverflow answer that elegantly explains how they differ and how to choose one over the other.
I highly recommend reading the full answer, but here's a gist of it.
require_relative 'script'
assumes that the relative path between the two Ruby source files will stay the same.require 'script'
assumes thatscript
is inside one of the directories on the load path ($LOAD_PATH
). This generally requires extra setup, since you have to add something to the load path.require './script'
assumes that the relative path from the Ruby process's current working directory toscript
is going to stay the same.
Hope that clears things a bit.
Conclusion
- Use
load
to pick up any changes you made to a file while the program is running. - Use
autoload
to speed up the initialization of your library by lazily loading the modules. - Use
require
when you want to use external gems. - Use
require_relative
for local files relative to the current working directory.
I hope you found this article useful and that you learned something new.
If you have any questions or feedback, didn't understand something, or found a mistake, please leave a comment below or send me an email. I look forward to hearing from you.
Please subscribe to my blog if you'd like to receive future articles directly in your email. If you're already a subscriber, thank you.