Module: Zeitwerk::Loader::Callbacks

Included in:
Zeitwerk::Loader
Defined in:
lib/zeitwerk/loader/callbacks.rb

Instance Method Summary collapse

Instance Method Details

#on_dir_autoloaded(dir) ⇒ void

This method returns an undefined value.

Invoked from our decorated Kernel#require when a managed directory is autoloaded.

Parameters:

  • dir (String)


19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/zeitwerk/loader/callbacks.rb', line 19

def on_dir_autoloaded(dir)
  # Module#autoload does not serialize concurrent requires, and we handle
  # directories ourselves.
  #
  # That introduces a race condition here in which thread t1 autovivifies the
  # module, and while autoloads are being set on that module object, thread t2
  # autoloads the same namespace.
  #
  # In that situation, t2 resets the constant to store a new module. That not
  # only sets the constant twice (undesirable per se), but it gets worse,
  # because the module object created by t2 won't have any of the autoloads
  # for child constants set, since t1 correctly deleted the lazy_dirs entry,
  # thus resulting in NameErrors when client code tries to reach them.
  mutex2.synchronize do
    parent, cname = autoloads[dir]
    break if loaded_cpaths.include?(cpath(parent, cname))

    autovivified_module = parent.const_set(cname, Module.new)
    log("module #{autovivified_module.name} autovivified from directory #{dir}") if logger

    loaded_cpaths.add(autovivified_module.name)
    on_namespace_loaded(autovivified_module)
  end
end

#on_file_autoloaded(file) ⇒ void

This method returns an undefined value.

Invoked from our decorated Kernel#require when a managed file is autoloaded.

Parameters:

  • file (String)


7
8
9
10
11
# File 'lib/zeitwerk/loader/callbacks.rb', line 7

def on_file_autoloaded(file)
  parent, cname = autoloads[file]
  loaded_cpaths.add(cpath(parent, cname))
  log("constant #{cpath(parent, cname)} loaded from file #{file}") if logger
end

#on_namespace_loaded(namespace) ⇒ void

This method returns an undefined value.

Invoked when a class or module is created or reopened, either from the tracer or from module autovivification. If the namespace has matching subdirectories, we descend into them now.

Parameters:

  • namespace (Module)


51
52
53
54
55
56
57
# File 'lib/zeitwerk/loader/callbacks.rb', line 51

def on_namespace_loaded(namespace)
  if subdirs = lazy_subdirs.delete(namespace.name)
    subdirs.each do |subdir|
      set_autoloads_in_dir(subdir, namespace)
    end
  end
end