---
title: "Rails 6 introduces new code loader called Zeitwerk"
description:
  "Rails 6 introduces new code loader named Zeitwerk with better Ruby semantics
  and threadsafety"
canonical_url: "https://www.bigbinary.com/blog/rails-6-introduces-new-code-loader-called-zeitwerk"
markdown_url: "https://www.bigbinary.com/blog/rails-6-introduces-new-code-loader-called-zeitwerk.md"
---

# Rails 6 introduces new code loader called Zeitwerk

Rails 6 introduces new code loader named Zeitwerk with better Ruby semantics and
threadsafety

- Author: Midhun Krishna
- Published: October 8, 2019
- Categories: Rails 6, Rails

[Zeitwerk](https://github.com/fxn/zeitwerk) is the new code loader that
[comes with Rails 6 by default](https://weblog.rubyonrails.org/2019/2/22/zeitwerk-integration-in-rails-6-beta-2#autoloading-modes).
In addition to providing
[autoloading, eager loading, and reloading capabilities](https://guides.rubyonrails.org/autoloading_and_reloading_constants.html),
it also improves the classical code loader by being efficient and thread safe.
According to the author of Zeitwerk, [Xavier Noria](https://twitter.com/fxn),
one of the main motivations for writing Zeitwerk was to keep code DRY and to
remove the brittle `require` calls.

Zeitwerk is available as a gem with no additional dependencies. It means any
regular Ruby project can use Zeitwerk.

### How to use Zeitwerk

Zeitwerk is baked in a Rails 6 project, thanks to the
[Zeitwerk-Rails integration](https://github.com/rails/rails/blob/bfc9065d58508fb19dd1a4170406604dd3b3234a/activesupport/lib/active_support/dependencies/zeitwerk_integration.rb).
For a non-Rails project, adding the following into the project's entry point
sets up Zeitwerk.

```ruby

loader = Zeitwerk::Loader.new
loader.push_dir(...)
loader.setup

```

For gem maintainers, Zeitwerk provides the handy `.for_gem` utility method

The following example from Zeitwerk documentation illustrates the usage of
`Zeitwerk.for_gem` method.

```ruby
#lib/my_gem.rb (main file)

require "zeitwerk"
loader = Zeitwerk::Loader.for_gem
loader.setup

module MyGem
  # Since the setup has been performed, at this point we are already
  # able to reference project constants, in this case MyGem::MyLogger.
  include MyLogger
end

```

### How does Zeitwerk work?

Before we look into Zeitwerk's internals, the following section provides a quick
refresher on constant-resolution in Ruby and how classical code loader of Rails
works.

Ruby's constant resolution looks for a constant in the following places.

- In each entry of Module.nesting
- In each entry of Module.ancestors

It triggers 'constant_missing' callback when it can't find the constant.

Ruby used to look for constants in Object.ancestors as well, but
[that seems not the case anymore](https://github.com/ruby/ruby/commit/44a2576f798b07139adde2d279e48fdbe71a0148).
An in-depth explanation of constant resolution can be found
[at Conrad Irwin's blog](https://cirw.in/blog/constant-lookup.html).

##### Classical Code Loader in Rails

Classical code loader (code loader in Rails version < 6.0) achieves autoloading
by overriding
[Module#const_missing](https://docs.ruby-lang.org/en/2.5.0/Module.html#method-i-const_missing)
and loads the missing constant without the need for an explicit require call as
long as the code follows certain conventions.

- The file should be within a directory in
  ActiveSupport::Dependencies.autoload_paths
- A file should be named after the class, i.e Admin::RoutesController =>
  admin/routes_controller.rb

##### Zeitwerk Mode

Zeitwerk takes an entirely different approach in autoloading by registering
constants to be autoloaded by Ruby.

Consider the following configuration in which Zeitwerk manages `lib` directory
and `lib` has `automobile.rb` file.

```ruby

loader.push_dir('./lib')

```

Zeitwerk then uses
[Module.autoload](https://docs.ruby-lang.org/en/2.5.0/Module.html#method-i-autoload)
to tell Ruby that "Automobile" can be found in "lib/automobile.rb".

```ruby

autoload "Automobile", "lib/automobile.rb"

```

Unlike classical loader, Zeitwerk takes module nesting into account while
loading constants by leveraging the new Tracepoint API to go look for constants
defined in subdirectories when a new class or module is defined.

Let us look at an example to understand this better.

```ruby

class Automobile
  # => Tracepoint hook triggers here.
  # include Engine
end

```

When
[the tracepoint hook](https://github.com/fxn/zeitwerk/blob/86064aba0c6e218c8bcc235b30c210a86c7c6ef8/lib/zeitwerk/explicit_namespace.rb#L78)
triggers, Zeitwerk checks for an `automobile` directory in the same level as
automobile.rb and sets up Module.autoload for that directory and all the files
(in this case ./automobile/engine.rb) within that directory.

### Conclusion

Previously in Rails, we had a code loader that was riddled with gotchas and
struggled to be thread safe. Zeitwerk does a better job by leveraging the new
Ruby standard API and matches Ruby's semantics for constants.

## Links

- [Human page](https://www.bigbinary.com/blog/rails-6-introduces-new-code-loader-called-zeitwerk)
