module Zeitwerk::Loader::Config
def actual_roots
def actual_roots reject do |root_dir, _root_namespace| ?(root_dir) || ignored_path?(root_dir)
def collapse(*glob_patterns)
Configure directories or glob patterns to be collapsed.
def collapse(*glob_patterns) glob_patterns = expand_paths(glob_patterns) mutex.synchronize do collapse_glob_patterns.merge(glob_patterns) collapse_dirs.merge(expand_glob_patterns(glob_patterns)) end end
def collapse?(dir)
def collapse?(dir) se_dirs.member?(dir)
def dirs(namespaces: false, ignored: false)
These are read-only collections, please add to them with `push_dir`.
If `ignored` is falsey (default), ignored root directories are filtered out.
values are their corresponding namespaces, class or module objects.
instead. Keys are the absolute paths of the root directories as strings,
paths of the root directories as strings. If truthy, returns a hash table
If `namespaces` is falsey (default), returns an array with the absolute
def dirs(namespaces: false, ignored: false) if namespaces if ignored || ignored_paths.empty? roots.clone else roots.reject { |root_dir, _namespace| ignored_path?(root_dir) } end else if ignored || ignored_paths.empty? roots.keys else roots.keys.reject { |root_dir| ignored_path?(root_dir) } end end.freeze end
def do_not_eager_load(*paths)
in those files are still autoloadable.
Let eager load ignore the given files or directories. The constants defined
def do_not_eager_load(*paths) mutex.synchronize { eager_load_exclusions.merge(expand_paths(paths)) } end
def enable_reloading
-
(Zeitwerk::Error)
-
def enable_reloading mutex.synchronize do break if @reloading_enabled if @setup raise Zeitwerk::Error, "cannot enable reloading after setup" else @reloading_enabled = true end end end
def excluded_from_eager_load?(abspath)
def excluded_from_eager_load?(abspath) mize this common use case. false if eager_load_exclusions.empty? p(abspath) do |path| rn true if eager_load_exclusions.member?(path) rn false if roots.key?(path)
def expand_glob_patterns(glob_patterns)
def expand_glob_patterns(glob_patterns) that Dir.glob works with regular file names just fine. That is, patterns technically need no wildcards. atterns.flat_map { |glob_pattern| Dir.glob(glob_pattern) }
def expand_paths(paths)
def expand_paths(paths) flatten.map! { |path| File.expand_path(path) }
def ignore(*glob_patterns)
Configure files, directories, or glob patterns to be totally ignored.
def ignore(*glob_patterns) glob_patterns = expand_paths(glob_patterns) mutex.synchronize do ignored_glob_patterns.merge(glob_patterns) ignored_paths.merge(expand_glob_patterns(glob_patterns)) end end
def ignored_path?(abspath)
def ignored_path?(abspath) d_paths.member?(abspath)
def ignores?(abspath)
descendant of an ignored directory.
Returns true if the argument has been configured to be ignored, or is a
def ignores?(abspath) n use case. false if ignored_paths.empty? (abspath) do |path| n true if ignored_path?(path) n false if roots.key?(path)
def initialize
def initialize @inflector = Zeitwerk::Inflector.new @logger = self.class.default_logger @tag = SecureRandom.hex(3) @initialized_at = Time.now @roots = {} @ignored_glob_patterns = Set.new @ignored_paths = Set.new @collapse_glob_patterns = Set.new @collapse_dirs = Set.new @eager_load_exclusions = Set.new @reloading_enabled = false @on_setup_callbacks = [] @on_load_callbacks = {} @on_unload_callbacks = {} end
def log!
Logs to `$stdout`, handy shortcut for debugging.
def log! @logger = ->(msg) { puts msg } end
def on_load(cpath = :ANY, &block)
-
(TypeError)
-
def on_load(cpath = :ANY, &block) raise TypeError, "on_load only accepts strings" unless cpath.is_a?(String) || cpath == :ANY mutex.synchronize do (on_load_callbacks[cpath] ||= []) << block end end
def on_setup(&block)
If setup was already done, the block runs immediately.
Configure a block to be called after setup and on each reload.
def on_setup(&block) mutex.synchronize do on_setup_callbacks << block block.call if @setup end end
def on_unload(cpath = :ANY, &block)
-
(TypeError)
-
def on_unload(cpath = :ANY, &block) raise TypeError, "on_unload only accepts strings" unless cpath.is_a?(String) || cpath == :ANY mutex.synchronize do (on_unload_callbacks[cpath] ||= []) << block end end
def push_dir(path, namespace: Object)
-
(Zeitwerk::Error)
-
def push_dir(path, namespace: Object) unless namespace.is_a?(Module) # Note that Class < Module. raise Zeitwerk::Error, "#{namespace.inspect} is not a class or module object, should be" end unless real_mod_name(namespace) raise Zeitwerk::Error, "root namespaces cannot be anonymous" end abspath = File.expand_path(path) if dir?(abspath) raise_if_conflicting_directory(abspath) roots[abspath] = namespace else raise Zeitwerk::Error, "the root directory #{abspath} does not exist" end end
def recompute_collapse_dirs
def recompute_collapse_dirs se_dirs.replace(expand_glob_patterns(collapse_glob_patterns))
def recompute_ignored_paths
def recompute_ignored_paths d_paths.replace(expand_glob_patterns(ignored_glob_patterns))
def reloading_enabled?
def reloading_enabled? @reloading_enabled end
def root_dir?(dir)
def root_dir?(dir) key?(dir)
def tag
writer below.
Implemented as a method instead of via attr_reader for symmetry with the
Returns the loader's tag.
def tag @tag end
def tag=(tag)
Sets a tag for the loader, useful for logging.
def tag=(tag) @tag = tag.to_s end