Module: Zeitwerk::Registry
- Defined in:
- lib/zeitwerk/registry.rb
Overview
:nodoc: all
Class Attribute Summary collapse
-
.autoloads ⇒ Object
readonly
Maps real paths to the loaders responsible for them.
-
.inceptions ⇒ Object
readonly
This hash table addresses an edge case in which an autoload is ignored.
-
.loaders ⇒ Object
readonly
Keeps track of all loaders.
-
.loaders_managing_gems ⇒ Object
readonly
Registers loaders created with ‘for_gem` to make the method idempotent in case of reload.
Class Method Summary collapse
- .inception?(cpath) ⇒ Boolean
- .loader_for(path) ⇒ Object
-
.loader_for_gem(root_file) ⇒ Object
This method returns always a loader, the same instance for the same root file.
- .on_unload(loader) ⇒ Object
- .register_autoload(loader, realpath) ⇒ Object
- .register_inception(cpath, realpath, loader) ⇒ Object
-
.register_loader(loader) ⇒ Object
Registers a loader.
- .unregister_autoload(realpath) ⇒ Object
Class Attribute Details
.autoloads ⇒ Object (readonly)
Maps real paths to the loaders responsible for them.
This information is used by our decorated ‘Kernel#require` to be able to invoke callbacks and autovivify modules.
27 28 29 |
# File 'lib/zeitwerk/registry.rb', line 27 def autoloads @autoloads end |
.inceptions ⇒ Object (readonly)
This hash table addresses an edge case in which an autoload is ignored.
For example, let’s suppose we want to autoload in a gem like this:
# lib/my_gem.rb
loader = Zeitwerk::Loader.new
loader.push_dir(__dir__)
loader.setup
module MyGem
end
if you require “my_gem”, as Bundler would do, this happens while setting up autoloads:
1. Object.autoload?(:MyGem) returns `nil` because the autoload for
the constant is issued by Zeitwerk while the same file is being
required.
2. The constant `MyGem` is undefined while setup runs.
Therefore, a directory ‘lib/my_gem` would autovivify a module according to the existing information. But that would be wrong.
To overcome this fundamental limitation, we keep track of the constant paths that are in this situation —in the example above, “MyGem”— and take this collection into account for the autovivification logic.
Note that you cannot generally address this by moving the setup code below the constant definition, because we want libraries to be able to use managed constants in the module body:
module MyGem
include MyConcern
end
66 67 68 |
# File 'lib/zeitwerk/registry.rb', line 66 def inceptions @inceptions end |
.loaders ⇒ Object (readonly)
Keeps track of all loaders. Useful to broadcast messages and to prevent them from being garbage collected.
11 12 13 |
# File 'lib/zeitwerk/registry.rb', line 11 def loaders @loaders end |
.loaders_managing_gems ⇒ Object (readonly)
Registers loaders created with ‘for_gem` to make the method idempotent in case of reload.
18 19 20 |
# File 'lib/zeitwerk/registry.rb', line 18 def loaders_managing_gems @loaders_managing_gems end |
Class Method Details
.inception?(cpath) ⇒ Boolean
111 112 113 114 115 |
# File 'lib/zeitwerk/registry.rb', line 111 def inception?(cpath) if pair = inceptions[cpath] pair.first end end |
.loader_for(path) ⇒ Object
119 120 121 |
# File 'lib/zeitwerk/registry.rb', line 119 def loader_for(path) autoloads[path] end |
.loader_for_gem(root_file) ⇒ Object
This method returns always a loader, the same instance for the same root file. That is how Zeitwerk::Loader.for_gem is idempotent.
81 82 83 84 85 86 87 88 89 |
# File 'lib/zeitwerk/registry.rb', line 81 def loader_for_gem(root_file) loaders_managing_gems[root_file] ||= begin Loader.new.tap do |loader| loader.tag = File.basename(root_file, ".rb") loader.inflector = GemInflector.new(root_file) loader.push_dir(File.dirname(root_file)) end end end |
.on_unload(loader) ⇒ Object
125 126 127 128 |
# File 'lib/zeitwerk/registry.rb', line 125 def on_unload(loader) autoloads.delete_if { |_path, object| object == loader } inceptions.delete_if { |_cpath, (_path, object)| object == loader } end |
.register_autoload(loader, realpath) ⇒ Object
93 94 95 |
# File 'lib/zeitwerk/registry.rb', line 93 def register_autoload(loader, realpath) autoloads[realpath] = loader end |
.register_inception(cpath, realpath, loader) ⇒ Object
105 106 107 |
# File 'lib/zeitwerk/registry.rb', line 105 def register_inception(cpath, realpath, loader) inceptions[cpath] = [realpath, loader] end |
.register_loader(loader) ⇒ Object
Registers a loader.
72 73 74 |
# File 'lib/zeitwerk/registry.rb', line 72 def register_loader(loader) loaders << loader end |
.unregister_autoload(realpath) ⇒ Object
99 100 101 |
# File 'lib/zeitwerk/registry.rb', line 99 def unregister_autoload(realpath) autoloads.delete(realpath) end |