skip to content

In Ruby, how do require, require_relative and load differ in how they find a file and how often they run it?

level: juniorimportance: must knowfreq 68%

answer

  1. search path vs the caller's directory
  2. true the first time, false after
  3. load runs the file every call
  4. load wants the full file name
  5. $LOADED_FEATURES records what ran

basics

~20 s

require searches $LOAD_PATH and runs a file once, returning true then false; require_relative resolves the path from the calling file's directory with the same once-only rule; load runs the named file on every call and returns true.

solid answer

~40 s

`require "name"` looks for `name.rb` (or a compiled extension) in the directories of `$LOAD_PATH`, runs it, records its absolute path in `$LOADED_FEATURES` and returns `true`; later calls for the same file return `false` without running it. `require_relative "name"` applies the same once-only rule but resolves the path against the directory of the file that contains the call, so it does not depend on the load path or the current working directory. `load "name.rb"` takes a file name with its extension, runs the file every time it is called, never records it in `$LOADED_FEATURES`, and returns `true`; an optional second argument runs the file inside a wrapper module. Use `require` for gems and the standard library, `require_relative` for files of your own project, and `load` when re-execution is the point.

code

ruby · 7 lines
ruby
require "json"            # => true  (ran json.rb)
require "json"            # => false (already in $LOADED_FEATURES)

load "plugins/seo.rb"      # => true  (runs the file)
load "plugins/seo.rb"      # => true  (runs it again)

require_relative "lib/page"  # resolved from this file's directory

go deeper

for a junior

Recall the three methods, that require and require_relative run a file once while load runs it every time, and what require returns on the second call.

for a middle

Explain how each finds its file: $LOAD_PATH, the calling file's directory, or the exact name, and why ./ paths depend on the working directory.

for a senior

Choose deliberately in a codebase: require_relative inside a gem or app, require for dependencies, load only where re-execution is designed in, and spot double-loading from mixed paths.

for a principal

Set loading conventions for shared code, such as one entry file per library and no load-path manipulation in library code, so behaviour never depends on how a program was started.

## Three ways to bring code into a Ruby program Ruby has no import statement; loading code means **executing another file**. Constants, classes, modules and methods that file defines become available afterwards, while its local variables stay private to it. The three core methods differ in two things: how the file is found, and whether it runs more than once. | | `require` | `require_relative` | `load` | |---|---|---|---| | Finds the file via | `$LOAD_PATH`, or an absolute path, or `./`/`../` from `Dir.pwd` | the directory of the calling file | the exact name: absolute, or searched in `$LOAD_PATH`, then the current directory | | Extension | optional; tries `.rb`, then the platform's extension suffix | optional | required (`"plugin.rb"`) | | Runs the file | once per process | once per process | every call | | Recorded in `$LOADED_FEATURES` | yes | yes | no | | Returns | `true`, then `false` | `true`, then `false` | `true` | | Missing file | `LoadError` | `LoadError` | `LoadError` | ## `require`: the library loader `require "json"` walks the directories in `$LOAD_PATH` in order and loads the first match. RubyGems and Bundler work by adding gem directories to that array, which is why the same call finds both standard-library files and installed gems. A name starting with `./` or `../` is resolved from the **current working directory**, not from the file that contains the call, a frequent source of scripts that only work when started from one directory. Once the file has run successfully, its absolute path goes into `$LOADED_FEATURES` (alias `$"`), and any later `require` that resolves to the same file returns `false` immediately. ## `require_relative`: files of your own project ```ruby # lib/sitegen/builder.rb require_relative "page" # lib/sitegen/page.rb require_relative "../sitegen" # lib/sitegen.rb ``` The path is joined to the directory of `builder.rb` itself, so the call works from any working directory and needs no load-path setup. It shares the once-only bookkeeping with `require`: a file loaded by `require_relative` and later by `require` through the load path resolves to the same absolute path and runs only once. It needs a real file to be relative to. In code run by `eval` without a file name it raises `LoadError` with the message `cannot infer basepath`. ## `load`: run it again - `load "config/plugins/seo.rb"` executes the file each time, which suits reloading edited code in a development loop or re-reading a Ruby-syntax configuration file. - Because nothing is recorded, constants the file defines are redefined on every call, which prints `already initialized constant` warnings. - `load(path, true)` runs the file inside a fresh anonymous module, so its top-level constants and methods do not land in `Object`; passing a module instead of `true` uses that module as the namespace. ## Choosing 1. A gem or standard-library feature: `require "name"`. 2. Another file in the same project or gem: `require_relative "path"`. 3. A file whose code must run again, deliberately: `load "path.rb"`. 4. Never `load` a library file to "make sure" it is loaded; that is what `require`'s return value already tells you. ## Return values in practice The `true`/`false` result is informational. Code rarely branches on it, but it is a quick check in `irb`: a `false` means the file had already been loaded, and editing it will not take effect until the process restarts or the file is loaded again with `load`. ## Traps interviewers probe - **Expecting `load` to be idempotent.** It is not; every call re-runs the file, including registrations and monkey patches at its top level. - **Expecting `require_relative` to follow the working directory.** It follows the file that contains the call. - **Passing a bare name to `load` and a full name to `require`.** `load "page"` looks for a file literally named `page`; `require "page.rb"` works but the extension is usually left off. - **Expecting local variables to cross files.** A local variable assigned at the top of a loaded file is gone when the file finishes; share values through constants, methods or explicit arguments instead.

  • Why can `require "./lib/page"` work in one shell and fail in another?
    A path beginning with `./` or `../` is resolved from `Dir.pwd`, the process's current working directory, not from the file that contains the call. Started from another directory, the path points elsewhere and `require` raises `LoadError`. `require_relative "lib/page"` fixes that by resolving from the calling file's own directory.
  • If a file is loaded once with `require_relative` and later with `require` through `$LOAD_PATH`, does it run twice?
    No. Both methods resolve the file to its absolute path and consult the same `$LOADED_FEATURES` bookkeeping, so the second call finds it already loaded and returns `false`. Running it twice takes `load`, or a second copy of the file at a different real path.

saying these in an interview costs you the question

  • require_relative is resolved from the current working directory
  • load skips files that require has already loaded
  • require returns nil when the file was already loaded
  • load appends .rb automatically, just like require
  • Local variables defined in a required file become visible to the caller