zeitwerk 2.1.5 → 2.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +9 -1
- data/lib/zeitwerk/loader.rb +48 -22
- data/lib/zeitwerk/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 43750607caaaa5d4fff5bd52204cafb98fbd5109b51a24d9099ba83c6a2a4990
|
4
|
+
data.tar.gz: 8ad3251fd93af9e66a9102c13556beff5805a38660d69e4c5de37e2808e76d8f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e6e87877104078f564686a15b81882a8e20a560a36999e0f8b9916aa520dd46fe1a2b7f65cacdb7b6c62d252472b6ce1370939054f026a335e21652881820814
|
7
|
+
data.tar.gz: 3641d412ab4b9176861b9ed9b28ea7964b6a814ebb72804c96967e511562fb87f424c48d7780345be8ccd2c53bdacfe095e3e5173e166a4185bf389740258ca6
|
data/README.md
CHANGED
@@ -338,7 +338,15 @@ This needs to be done before calling `setup`.
|
|
338
338
|
<a id="markdown-logging" name="logging"></a>
|
339
339
|
### Logging
|
340
340
|
|
341
|
-
Zeitwerk is silent by default, but you can
|
341
|
+
Zeitwerk is silent by default, but you can ask loaders to trace their activity. Logging is meant just for troubleshooting, shouldn't normally be enabled.
|
342
|
+
|
343
|
+
The `log!` mehtod is a quick shortcut to let the loader log to `$stdout`:
|
344
|
+
|
345
|
+
```
|
346
|
+
loader.log!
|
347
|
+
```
|
348
|
+
|
349
|
+
If you want more control, a logger can be configured as a callable
|
342
350
|
|
343
351
|
```ruby
|
344
352
|
loader.logger = method(:puts)
|
data/lib/zeitwerk/loader.rb
CHANGED
@@ -53,6 +53,23 @@ module Zeitwerk
|
|
53
53
|
# @return [Set<String>]
|
54
54
|
attr_reader :ignored_paths
|
55
55
|
|
56
|
+
# A _shadowed file_ is a file managed by this loader that is ignored when
|
57
|
+
# setting autoloads because its matching constant is taken. Either the
|
58
|
+
# constant is already defined, or there exists an autoload for it.
|
59
|
+
#
|
60
|
+
# Think $LOAD_PATH and require, only the first occurrence of a given
|
61
|
+
# relative name is loaded.
|
62
|
+
#
|
63
|
+
# This set keeps track of the absolute path of shadowed files, to be able to
|
64
|
+
# skip them while eager loading.
|
65
|
+
#
|
66
|
+
# Note this cannot be implemented with do_not_eager_load because these
|
67
|
+
# files are not autoloadable.
|
68
|
+
#
|
69
|
+
# @private
|
70
|
+
# @return [Set<String>]
|
71
|
+
attr_reader :shadowed_files
|
72
|
+
|
56
73
|
# Maps real absolute paths for which an autoload has been set ---and not
|
57
74
|
# executed--- to their corresponding parent class or module and constant
|
58
75
|
# name.
|
@@ -138,6 +155,7 @@ module Zeitwerk
|
|
138
155
|
@autoloaded_dirs = []
|
139
156
|
@to_unload = {}
|
140
157
|
@lazy_subdirs = {}
|
158
|
+
@shadowed_files = Set.new
|
141
159
|
@eager_load_exclusions = Set.new
|
142
160
|
|
143
161
|
# TODO: find a better name for these mutexes.
|
@@ -306,6 +324,7 @@ module Zeitwerk
|
|
306
324
|
autoloaded_dirs.clear
|
307
325
|
to_unload.clear
|
308
326
|
lazy_subdirs.clear
|
327
|
+
shadowed_files.clear
|
309
328
|
|
310
329
|
Registry.on_unload(self)
|
311
330
|
ExplicitNamespace.unregister(self)
|
@@ -343,19 +362,19 @@ module Zeitwerk
|
|
343
362
|
|
344
363
|
queue = actual_root_dirs.reject { |dir| eager_load_exclusions.member?(dir) }
|
345
364
|
while dir = queue.shift
|
346
|
-
|
347
|
-
|
348
|
-
each_abspath(dir) do |abspath|
|
365
|
+
ls(dir) do |_basename, abspath|
|
349
366
|
next if eager_load_exclusions.member?(abspath)
|
350
367
|
|
351
368
|
if ruby?(abspath)
|
352
|
-
|
369
|
+
require abspath unless shadowed_files.member?(abspath)
|
353
370
|
elsif dir?(abspath)
|
354
371
|
queue << abspath
|
355
372
|
end
|
356
373
|
end
|
357
374
|
end
|
358
375
|
|
376
|
+
shadowed_files.clear
|
377
|
+
|
359
378
|
autoloaded_dirs.each do |autoloaded_dir|
|
360
379
|
Registry.unregister_autoload(autoloaded_dir)
|
361
380
|
end
|
@@ -391,6 +410,13 @@ module Zeitwerk
|
|
391
410
|
to_unload.keys.freeze
|
392
411
|
end
|
393
412
|
|
413
|
+
# Logs to `$stdout`, handy shortcut for debugging.
|
414
|
+
#
|
415
|
+
# @return [void]
|
416
|
+
def log!
|
417
|
+
@logger = ->(msg) { puts msg }
|
418
|
+
end
|
419
|
+
|
394
420
|
# --- Class methods ---------------------------------------------------------------------------
|
395
421
|
|
396
422
|
class << self
|
@@ -414,7 +440,7 @@ module Zeitwerk
|
|
414
440
|
#
|
415
441
|
# @return [Zeitwerk::Loader]
|
416
442
|
def for_gem
|
417
|
-
called_from = caller_locations.first.path
|
443
|
+
called_from = caller_locations(1, 1).first.path
|
418
444
|
Registry.loader_for_gem(called_from)
|
419
445
|
end
|
420
446
|
|
@@ -449,9 +475,10 @@ module Zeitwerk
|
|
449
475
|
# @param parent [Module]
|
450
476
|
# @return [void]
|
451
477
|
def set_autoloads_in_dir(dir, parent)
|
452
|
-
|
453
|
-
|
454
|
-
|
478
|
+
ls(dir) do |basename, abspath|
|
479
|
+
if ruby?(basename)
|
480
|
+
basename.slice!(-3, 3)
|
481
|
+
cname = inflector.camelize(basename, abspath).to_sym
|
455
482
|
autoload_file(parent, cname, abspath)
|
456
483
|
elsif dir?(abspath)
|
457
484
|
# In a Rails application, `app/models/concerns` is a subdirectory of
|
@@ -460,7 +487,10 @@ module Zeitwerk
|
|
460
487
|
# To resolve the ambiguity file name -> constant path this introduces,
|
461
488
|
# the `app/models/concerns` directory is totally ignored as a namespace,
|
462
489
|
# it counts only as root. The guard checks that.
|
463
|
-
|
490
|
+
unless root_dirs.key?(abspath)
|
491
|
+
cname = inflector.camelize(basename, abspath).to_sym
|
492
|
+
autoload_subdir(parent, cname, abspath)
|
493
|
+
end
|
464
494
|
end
|
465
495
|
end
|
466
496
|
end
|
@@ -496,6 +526,7 @@ module Zeitwerk
|
|
496
526
|
if autoload_path = autoload_for?(parent, cname)
|
497
527
|
# First autoload for a Ruby file wins, just ignore subsequent ones.
|
498
528
|
if ruby?(autoload_path)
|
529
|
+
shadowed_files.add(file)
|
499
530
|
log("file #{file} is ignored because #{autoload_path} has precedence") if logger
|
500
531
|
else
|
501
532
|
promote_namespace_from_implicit_to_explicit(
|
@@ -506,6 +537,7 @@ module Zeitwerk
|
|
506
537
|
)
|
507
538
|
end
|
508
539
|
elsif cdef?(parent, cname)
|
540
|
+
shadowed_files.add(file)
|
509
541
|
log("file #{file} is ignored because #{cpath(parent, cname)} is already defined") if logger
|
510
542
|
else
|
511
543
|
set_autoload(parent, cname, file)
|
@@ -605,7 +637,7 @@ module Zeitwerk
|
|
605
637
|
# @param dir [String]
|
606
638
|
# @return [void]
|
607
639
|
def do_preload_dir(dir)
|
608
|
-
|
640
|
+
ls(dir) do |_basename, abspath|
|
609
641
|
do_preload_abspath(abspath)
|
610
642
|
end
|
611
643
|
end
|
@@ -625,13 +657,13 @@ module Zeitwerk
|
|
625
657
|
end
|
626
658
|
|
627
659
|
# @param dir [String]
|
628
|
-
# @yieldparam path [String]
|
660
|
+
# @yieldparam path [String, String]
|
629
661
|
# @return [void]
|
630
|
-
def
|
631
|
-
Dir.foreach(dir) do |
|
632
|
-
next if
|
633
|
-
abspath = File.join(dir,
|
634
|
-
yield abspath unless ignored_paths.member?(abspath)
|
662
|
+
def ls(dir)
|
663
|
+
Dir.foreach(dir) do |basename|
|
664
|
+
next if basename.start_with?(".")
|
665
|
+
abspath = File.join(dir, basename)
|
666
|
+
yield basename, abspath unless ignored_paths.member?(abspath)
|
635
667
|
end
|
636
668
|
end
|
637
669
|
|
@@ -664,12 +696,6 @@ module Zeitwerk
|
|
664
696
|
parent.const_defined?(cname, false)
|
665
697
|
end
|
666
698
|
|
667
|
-
def const_get_if_autoload(abspath)
|
668
|
-
if cref = autoloads[File.realpath(abspath)]
|
669
|
-
cref[0].const_get(cref[1], false)
|
670
|
-
end
|
671
|
-
end
|
672
|
-
|
673
699
|
def register_explicit_namespace(cpath)
|
674
700
|
ExplicitNamespace.register(cpath, self)
|
675
701
|
end
|
data/lib/zeitwerk/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zeitwerk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Xavier Noria
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-04-
|
11
|
+
date: 2019-04-30 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |2
|
14
14
|
Zeitwerk implements constant autoloading with Ruby semantics. Each gem
|