skip to content

Require & Load Path

require loads a feature once by searching $LOAD_PATH, require_relative resolves from the calling file, and load re-runs a file each time. Interviewers probe double loading and autoload races.

on this pageshow

explore

questions

5

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
open as a page

In Ruby, how does require search $LOAD_PATH, and how does $LOADED_FEATURES enforce its once-only rule?

level: middleimportance: must knowfreq 42%

basics

~20 s

require tries each $LOAD_PATH directory in order and loads the first match. After a successful load it records the file's absolute path in $LOADED_FEATURES and skips any later require resolving to that same file; a load that raised is not recorded.

open as a page

In Ruby, how do Kernel#autoload and Module#autoload defer loading, and what does autoload? report?

level: middleimportance: should knowfreq 30%

basics

~20 s

autoload(:Name, "path") registers a constant whose first reference calls require on the path. Module#autoload registers it inside that module; Kernel#autoload in the current namespace. autoload? returns the pending path, or nil once loaded or never registered.

open as a page

A Ruby static-site generator's plugin loader runs each plugin twice after a rebuild; how do require, load and wrap explain and fix it?

level: seniorimportance: should knowfreq 24%

basics

~20 s

The loader uses load, which re-runs every plugin file on each rebuild, so registration side effects repeat. Either require plugins once, or keep load and reset the registry first, isolating each build's constants with load(path, true) or a fresh module.

open as a page

In Ruby, what happens when several threads reference the same not-yet-loaded autoload constant, and what can still go wrong?

level: seniorimportance: nice to knowfreq 18%

basics

~20 s

One thread runs the require while others wait; they see the constant only once the file has loaded. Remaining risks: two threads autoloading mutually dependent files can deadlock, and errors surface in whichever thread arrived first.

open as a page