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.
-
.gem_loaders_by_root_file ⇒ Object
readonly
Registers gem loaders to let ‘for_gem` be idempotent in case of reload.
-
.inceptions ⇒ Object
readonly
This hash table addresses an edge case in which an autoload is ignored.
-
.loaders ⇒ Object
readonly
Keeps track of all loaders.
Class Method Summary collapse
- .inception?(cpath, registered_by_loader = nil) ⇒ Boolean
- .loader_for(path) ⇒ Object
-
.loader_for_gem(root_file, namespace:, warn_on_extra_files:) ⇒ 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.
26 27 28 |
# File 'lib/zeitwerk/registry.rb', line 26 def autoloads @autoloads end |
.gem_loaders_by_root_file ⇒ Object (readonly)
Registers gem loaders to let ‘for_gem` be idempotent in case of reload.
17 18 19 |
# File 'lib/zeitwerk/registry.rb', line 17 def gem_loaders_by_root_file @gem_loaders_by_root_file 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
65 66 67 |
# File 'lib/zeitwerk/registry.rb', line 65 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 |
Class Method Details
.inception?(cpath, registered_by_loader = nil) ⇒ Boolean
113 114 115 116 117 118 119 120 |
# File 'lib/zeitwerk/registry.rb', line 113 def inception?(cpath, registered_by_loader=nil) if pair = inceptions[cpath] abspath, loader = pair if registered_by_loader.nil? || registered_by_loader.equal?(loader) abspath end end end |
.loader_for(path) ⇒ Object
124 125 126 |
# File 'lib/zeitwerk/registry.rb', line 124 def loader_for(path) autoloads[path] end |
.loader_for_gem(root_file, namespace:, warn_on_extra_files:) ⇒ Object
This method returns always a loader, the same instance for the same root file. That is how Zeitwerk::Loader.for_gem is idempotent.
89 90 91 |
# File 'lib/zeitwerk/registry.rb', line 89 def loader_for_gem(root_file, namespace:, warn_on_extra_files:) gem_loaders_by_root_file[root_file] ||= GemLoader.__new(root_file, namespace: namespace, warn_on_extra_files: warn_on_extra_files) end |
.on_unload(loader) ⇒ Object
130 131 132 133 |
# File 'lib/zeitwerk/registry.rb', line 130 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
95 96 97 |
# File 'lib/zeitwerk/registry.rb', line 95 def register_autoload(loader, abspath) autoloads[abspath] = loader end |
.register_inception(cpath, abspath, loader) ⇒ Object
107 108 109 |
# File 'lib/zeitwerk/registry.rb', line 107 def register_inception(cpath, abspath, loader) inceptions[cpath] = [abspath, loader] end |
.register_loader(loader) ⇒ Object
Registers a loader.
71 72 73 |
# File 'lib/zeitwerk/registry.rb', line 71 def register_loader(loader) loaders << loader end |
.unregister_autoload(abspath) ⇒ Object
101 102 103 |
# File 'lib/zeitwerk/registry.rb', line 101 def unregister_autoload(abspath) autoloads.delete(abspath) end |
.unregister_loader(loader) ⇒ Object
77 78 79 80 81 82 |
# File 'lib/zeitwerk/registry.rb', line 77 def unregister_loader(loader) loaders.delete(loader) gem_loaders_by_root_file.delete_if { |_, l| l == loader } autoloads.delete_if { |_, l| l == loader } inceptions.delete_if { |_, (_, l)| l == loader } end |