Ruby imports (require, load, etc.)
Back to ruby
How do we import Ruby from external files into the current script?
The simplest is load()
, which loads and executes a Ruby source file by name or path (relative to the current working directory). The file does not need to have an .rb
extension.
load '/path/to/foo2.rb' # absolute path load './foo2.rb' # relative path load 'foo2.rb' # searches $LOAD_PATH, then current dir load './foo1' # no .rb will work load 'foo1' # implicit current dir will work
Classes, definitions, and global from the loaded file will be available, but NOT local variables.
load './foo2.rb' # "foo1 executing..." puts Foo2.new.hi # "Hi!" puts fn_foo2 # "Hello!" puts $global_foo2 # "Hello world!" puts foo2 # ERROR
You can load more than once:
load './foo1' # "foo1 executing..." load './foo1' # "foo1 executing..."
require()
is very similar except source files have more rigid path and filename requirements, and the file will only execute once, even if you require it multiple times.
require 'foo2.rb' # ERROR! (needs explicit path) require './foo2.rb' # "foo2.rb executing..." --> true require './foo2.rb' # --> false require './foo1' # ERROR! (needs .rb extension)
The require_relative()
method is identical to require()
except that the file is searched for relative to the file doing the importing, not the current working directory.
All of these are in the "Kernel" module (and thus always
available in the current scope when you start up Ruby).
Here’s the official documentation for Ruby 3.0.6 where you
can get the full details such as return values and the
wrap
parameter for load:
My test files
To perform tests for the above examples, I wrote a little script to generate nearly identical source files with a puts statement, a class, a gloabl method, a local variable, and a global variable. Here’s the script:
if not Dir.exist? 'bar' Dir.mkdir 'bar' end { # For each name/path... foo1: 'foo1', foo2: 'foo2.rb', bar1: 'bar/bar1', bar2: 'bar/bar2.rb', }.each do |k, path| # Write a script with class and freestanding method File.open(path, 'w') do |f| f.puts <<~CODE puts "#{path} executing..." class #{k.to_s.capitalize} def hi puts "Hi" end end def fn_#{k.to_s} puts "Hello" end $global_#{k.to_s} = "hello world" CODE end end
The output looks like this:
$ tree . ├── bar │ ├── bar1 │ └── bar2.rb ├── foo1 └── foo2.rb $ cat foo1 puts "foo1 executing..." class Foo1 def hi puts "Hi" end end def fn_foo1 puts "Hello" end $global_foo1 = "hello world"
(I ended up not using the bar/
directory example
files as much as I thought I would.)
Then I simply tried different things interactively
with irb
:
$ irb irb(main):001:0> load 'foo1' foo1 executing... => true irb(main):002:0>