Module: Zeitwerk::Registry
- Defined in:
- lib/zeitwerk/registry.rb
Overview
:nodoc: all
Class Attribute Summary collapse
-
.autoloads ⇒ Object
readonly
Maps absolute 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, abspath) ⇒ Object
- .register_inception(cpath, abspath, loader) ⇒ Object
-
.register_loader(loader) ⇒ Object
Registers a loader.
- .unregister_autoload(abspath) ⇒ Object
- .unregister_loader(loader) ⇒ Object
Class Attribute Details
.autoloads ⇒ Object (readonly)
Maps absolute 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
120 121 122 123 124 |
# File 'lib/zeitwerk/registry.rb', line 120 def inception?(cpath) if pair = inceptions[cpath] pair.first end end |
.loader_for(path) ⇒ Object
128 129 130 |
# File 'lib/zeitwerk/registry.rb', line 128 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.
90 91 92 93 94 95 96 97 98 |
# File 'lib/zeitwerk/registry.rb', line 90 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
134 135 136 137 |
# File 'lib/zeitwerk/registry.rb', line 134 def on_unload(loader) autoloads.delete_if { |_path, object| object == loader } inceptions.delete_if { |_cpath, (_path, object)| object == loader } end |
.register_autoload(loader, abspath) ⇒ Object
102 103 104 |
# File 'lib/zeitwerk/registry.rb', line 102 def register_autoload(loader, abspath) autoloads[abspath] = loader end |
.register_inception(cpath, abspath, loader) ⇒ Object
114 115 116 |
# File 'lib/zeitwerk/registry.rb', line 114 def register_inception(cpath, abspath, loader) inceptions[cpath] = [abspath, 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(abspath) ⇒ Object
108 109 110 |
# File 'lib/zeitwerk/registry.rb', line 108 def unregister_autoload(abspath) autoloads.delete(abspath) end |
.unregister_loader(loader) ⇒ Object
78 79 80 81 82 83 |
# File 'lib/zeitwerk/registry.rb', line 78 def unregister_loader(loader) loaders.delete(loader) loaders_managing_gems.delete_if { |_, l| l == loader } autoloads.delete_if { |_, l| l == loader } inceptions.delete_if { |_, (_, l)| l == loader } end |