zeitwerk 2.6.12 → 2.6.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +81 -6
- data/lib/zeitwerk/gem_loader.rb +1 -2
- data/lib/zeitwerk/kernel.rb +0 -4
- data/lib/zeitwerk/loader/eager_load.rb +7 -7
- data/lib/zeitwerk/loader/helpers.rb +18 -5
- data/lib/zeitwerk/loader.rb +67 -33
- data/lib/zeitwerk/null_inflector.rb +5 -0
- data/lib/zeitwerk/version.rb +1 -1
- data/lib/zeitwerk.rb +1 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8177bcca0fd5895bbe28b19dc5fd04a810e2905f21f33924786a33a317c96207
|
4
|
+
data.tar.gz: 7e441521285fe28230dadfb4c5c9d40564e376dd651ddae043190c5fdd3ee526
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 57e0e401c952a13d1b96a8993bbee930132f2b63252ff7cd6646ceeeb5a3de886d1c36a8cdbc06e9add3e16e76bacd08cc8e32b58289fa01e9eabea4dad25581
|
7
|
+
data.tar.gz: e56116c8325ab38f751b8497f8270544543e950f92624c755b5d3d7bb296b48ce4afa668e1b4daae546561ddfa344fd9c650c7114c9cd2c637a514f0ebd38c98
|
data/README.md
CHANGED
@@ -40,6 +40,7 @@
|
|
40
40
|
- [Inflection](#inflection)
|
41
41
|
- [Zeitwerk::Inflector](#zeitwerkinflector)
|
42
42
|
- [Zeitwerk::GemInflector](#zeitwerkgeminflector)
|
43
|
+
- [Zeitwerk::NullInflector](#zeitwerknullinflector)
|
43
44
|
- [Custom inflector](#custom-inflector)
|
44
45
|
- [Callbacks](#callbacks)
|
45
46
|
- [The on_setup callback](#the-on_setup-callback)
|
@@ -59,6 +60,7 @@
|
|
59
60
|
- [Introspection](#introspection)
|
60
61
|
- [`Zeitwerk::Loader#dirs`](#zeitwerkloaderdirs)
|
61
62
|
- [`Zeitwerk::Loader#cpath_expected_at`](#zeitwerkloadercpath_expected_at)
|
63
|
+
- [`Zeitwerk::Loader#all_expected_cpaths`](#zeitwerkloaderall_expected_cpaths)
|
62
64
|
- [Encodings](#encodings)
|
63
65
|
- [Rules of thumb](#rules-of-thumb)
|
64
66
|
- [Debuggers](#debuggers)
|
@@ -258,7 +260,7 @@ app/controllers/admin/users_controller.rb -> Admin::UsersController
|
|
258
260
|
|
259
261
|
and does not have a file called `admin.rb`, Zeitwerk automatically creates an `Admin` module on your behalf the first time `Admin` is used.
|
260
262
|
|
261
|
-
To trigger this behavior, the directory must contain non-ignored Ruby files with the
|
263
|
+
To trigger this behavior, the directory must contain non-ignored Ruby files with the ".rb" extension, either directly or recursively. Otherwise, the directory is ignored. This condition is reevaluated during reloads.
|
262
264
|
|
263
265
|
<a id="markdown-explicit-namespaces" name="explicit-namespaces"></a>
|
264
266
|
### Explicit namespaces
|
@@ -373,7 +375,7 @@ require "zeitwerk"
|
|
373
375
|
loader = Zeitwerk::Loader.new
|
374
376
|
loader.tag = File.basename(__FILE__, ".rb")
|
375
377
|
loader.inflector = Zeitwerk::GemInflector.new(__FILE__)
|
376
|
-
loader.push_dir(
|
378
|
+
loader.push_dir(File.dirname(__FILE__))
|
377
379
|
```
|
378
380
|
|
379
381
|
If the main module references project constants at the top-level, Zeitwerk has to be ready to load them. Their definitions, in turn, may reference other project constants. And this is recursive. Therefore, it is important that the `setup` call happens above the main module definition:
|
@@ -579,7 +581,7 @@ root_dir2/my_app/routes
|
|
579
581
|
root_dir3/my_app/routes
|
580
582
|
```
|
581
583
|
|
582
|
-
where `
|
584
|
+
where `root_dir{1,2,3}` are root directories, eager loading `MyApp::Routes` will eager load the contents of the three corresponding directories.
|
583
585
|
|
584
586
|
There might exist external source trees implementing part of the namespace. This happens routinely, because top-level constants are stored in the globally shared `Object`. It happens also when deliberately [reopening third-party namespaces](#reopening-third-party-namespaces). Such external code is not eager loaded, the implementation is carefully scoped to what the receiver manages to avoid side-effects elsewhere.
|
585
587
|
|
@@ -774,6 +776,31 @@ This inflector is like the basic one, except it expects `lib/my_gem/version.rb`
|
|
774
776
|
|
775
777
|
The inflectors of different loaders are independent of each other. There are no global inflection rules or global configuration that can affect this inflector. It is deterministic.
|
776
778
|
|
779
|
+
<a id="markdown-zeitwerknullinflector" name="zeitwerknullinflector"></a>
|
780
|
+
#### Zeitwerk::NullInflector
|
781
|
+
|
782
|
+
This is an experimental inflector that simply returns its input unchanged.
|
783
|
+
|
784
|
+
```ruby
|
785
|
+
loader.inflector = Zeitwerk::NullInflector.new
|
786
|
+
```
|
787
|
+
|
788
|
+
In a project using this inflector, the names of files and directories are equal to the constants they define:
|
789
|
+
|
790
|
+
```
|
791
|
+
User.rb -> User
|
792
|
+
HTMLParser.rb -> HTMLParser
|
793
|
+
Admin/Role.rb -> Admin::Role
|
794
|
+
```
|
795
|
+
|
796
|
+
Point is, you think less. Names that typically need custom configuration like acronyms no longer require your attention. What you see is what you get, simple.
|
797
|
+
|
798
|
+
This inflector is experimental since Ruby usually goes for snake case in files and directories. But hey, if you fancy giving it a whirl, go for it!
|
799
|
+
|
800
|
+
The null inflector cannot be used in Rails applications because the `main` autoloader also manages engines. However, you could subclass the default inflector and override `camelize` to return the basename untouched if it starts with an uppercase letter. Generators would not create the expected file names, but you could still experiment to see how far this approach takes you.
|
801
|
+
|
802
|
+
In case-insensitive file systems, this inflector works as long as directory listings return the expected strings. Zeitwerk lists directories using Ruby APIs like `Dir.children` or `Dir.entries`.
|
803
|
+
|
777
804
|
<a id="markdown-custom-inflector" name="custom-inflector"></a>
|
778
805
|
#### Custom inflector
|
779
806
|
|
@@ -1006,7 +1033,7 @@ Zeitwerk::Loader.default_logger = method(:puts)
|
|
1006
1033
|
|
1007
1034
|
If there is a logger configured, you'll see traces when autoloads are set, files loaded, and modules autovivified. While reloading, removed autoloads and unloaded objects are also traced.
|
1008
1035
|
|
1009
|
-
As a curiosity, if your project has namespaces you'll notice in the traces Zeitwerk sets autoloads for _directories_.
|
1036
|
+
As a curiosity, if your project has namespaces you'll notice in the traces Zeitwerk sets autoloads for _directories_. This allows descending into subdirectories on demand, thus avoiding unnecessary tree walks.
|
1010
1037
|
|
1011
1038
|
<a id="markdown-loader-tag" name="loader-tag"></a>
|
1012
1039
|
#### Loader tag
|
@@ -1032,7 +1059,7 @@ Zeitwerk@my_gem: constant MyGem::Foo loaded from ...
|
|
1032
1059
|
<a id="markdown-ignoring-parts-of-the-project" name="ignoring-parts-of-the-project"></a>
|
1033
1060
|
### Ignoring parts of the project
|
1034
1061
|
|
1035
|
-
Zeitwerk ignores automatically any file or directory whose name starts with a dot, and any files that do not have extension ".rb".
|
1062
|
+
Zeitwerk ignores automatically any file or directory whose name starts with a dot, and any files that do not have the extension ".rb".
|
1036
1063
|
|
1037
1064
|
However, sometimes it might still be convenient to tell Zeitwerk to completely ignore some particular Ruby file or directory. That is possible with `ignore`, which accepts an arbitrary number of strings or `Pathname` objects, and also an array of them.
|
1038
1065
|
|
@@ -1304,6 +1331,54 @@ loader.cpath_expected_at("8.rb") # => Zeitwerk::NameError
|
|
1304
1331
|
|
1305
1332
|
This method does not parse file contents and does not guarantee files define the returned constant path. It just says which is the _expected_ one.
|
1306
1333
|
|
1334
|
+
`Zeitwerk::Loader#cpath_expected_at` is designed to be used with individual paths. If you want to know all the expected constant paths in the project, please use `Zeitwerk::Loader#all_expected_cpaths`, documented next.
|
1335
|
+
|
1336
|
+
<a id="markdown-zeitwerkloaderall_expected_cpaths" name="zeitwerkloaderall_expected_cpaths"></a>
|
1337
|
+
#### `Zeitwerk::Loader#all_expected_cpaths`
|
1338
|
+
|
1339
|
+
The method `Zeitwerk::Loader#all_expected_cpaths` returns a hash that maps the absolute paths of the files and directories managed by the receiver to their expected constant paths.
|
1340
|
+
|
1341
|
+
Ignored files, hidden files, and files whose extension is not ".rb" are not included in the result. Same for directories, hidden or ignored directories are not included in the result. Additionally, directories that contain no files with extension ".rb" (recursively) are also excluded, since those are not considered to represent Ruby namespaces.
|
1342
|
+
|
1343
|
+
For example, if `lib` is the root directory of a gem with the following contents:
|
1344
|
+
|
1345
|
+
```
|
1346
|
+
lib/.DS_Store
|
1347
|
+
lib/my_gem.rb
|
1348
|
+
lib/my_gem/version.rb
|
1349
|
+
lib/my_gem/ignored.rb
|
1350
|
+
lib/my_gem/drivers/unix.rb
|
1351
|
+
lib/my_gem/drivers/windows.rb
|
1352
|
+
lib/my_gem/collapsed/foo.rb
|
1353
|
+
lib/tasks/my_gem.rake
|
1354
|
+
```
|
1355
|
+
|
1356
|
+
`Zeitwerk::Loader#all_expected_cpaths` would return (maybe in a different order):
|
1357
|
+
|
1358
|
+
```ruby
|
1359
|
+
{
|
1360
|
+
"/.../lib" => "Object",
|
1361
|
+
"/.../lib/my_gem.rb" => "MyGem",
|
1362
|
+
"/.../lib/my_gem" => "MyGem",
|
1363
|
+
"/.../lib/my_gem/version.rb" => "MyGem::VERSION",
|
1364
|
+
"/.../lib/my_gem/drivers" => "MyGem::Drivers",
|
1365
|
+
"/.../lib/my_gem/drivers/unix.rb" => "MyGem::Drivers::Unix",
|
1366
|
+
"/.../lib/my_gem/drivers/windows.rb" => "MyGem::Drivers::Windows",
|
1367
|
+
"/.../lib/my_gem/collapsed" => "MyGem"
|
1368
|
+
"/.../lib/my_gem/collapsed/foo.rb" => "MyGem::Foo"
|
1369
|
+
}
|
1370
|
+
```
|
1371
|
+
|
1372
|
+
In the previous example we assume `lib/my_gem/ignored.rb` is ignored, and therefore it is not present in the returned hash. Also, `lib/my_gem/collapsed` is a collapsed directory, so the expected namespace at that level is still `MyGem` (this is an edge case).
|
1373
|
+
|
1374
|
+
The file `lib/.DS_Store` is hidden, hence excluded. The directory `lib/tasks` is also not present because it contains no files with extension ".rb".
|
1375
|
+
|
1376
|
+
Directory paths do not have trailing slashes.
|
1377
|
+
|
1378
|
+
The order of the hash entries is undefined.
|
1379
|
+
|
1380
|
+
This method does not parse or execute file contents and does not guarantee files define the corresponding constant paths. It just says which are the _expected_ ones.
|
1381
|
+
|
1307
1382
|
<a id="markdown-encodings" name="encodings"></a>
|
1308
1383
|
### Encodings
|
1309
1384
|
|
@@ -1325,7 +1400,7 @@ The test suite passes on Windows with codepage `Windows-1252` if all the involve
|
|
1325
1400
|
|
1326
1401
|
3. In that line, if two loaders manage files that translate to the same constant in the same namespace, the first one wins, the rest are ignored. Similar to what happens with `require` and `$LOAD_PATH`, only the first occurrence matters.
|
1327
1402
|
|
1328
|
-
4. Projects that reopen a namespace defined by some dependency have to ensure said namespace is loaded before setup. That is, the project has to make sure it reopens, rather than
|
1403
|
+
4. Projects that reopen a namespace defined by some dependency have to ensure said namespace is loaded before setup. That is, the project has to make sure it reopens, rather than defines, the namespace. This is often accomplished by loading (e.g., `require`-ing) the dependency.
|
1329
1404
|
|
1330
1405
|
5. Objects stored in reloadable constants should not be cached in places that are not reloaded. For example, non-reloadable classes should not subclass a reloadable class, or mixin a reloadable module. Otherwise, after reloading, those classes or module objects would become stale. Referring to constants in dynamic places like method calls or lambdas is fine.
|
1331
1406
|
|
data/lib/zeitwerk/gem_loader.rb
CHANGED
@@ -42,13 +42,12 @@ module Zeitwerk
|
|
42
42
|
def warn_on_extra_files
|
43
43
|
expected_namespace_dir = @root_file.delete_suffix(".rb")
|
44
44
|
|
45
|
-
ls(@root_dir) do |basename, abspath|
|
45
|
+
ls(@root_dir) do |basename, abspath, ftype|
|
46
46
|
next if abspath == @root_file
|
47
47
|
next if abspath == expected_namespace_dir
|
48
48
|
|
49
49
|
basename_without_ext = basename.delete_suffix(".rb")
|
50
50
|
cname = inflector.camelize(basename_without_ext, abspath).to_sym
|
51
|
-
ftype = dir?(abspath) ? "directory" : "file"
|
52
51
|
|
53
52
|
warn(<<~EOS)
|
54
53
|
WARNING: Zeitwerk defines the constant #{cname} after the #{ftype}
|
data/lib/zeitwerk/kernel.rb
CHANGED
@@ -14,10 +14,6 @@ module Kernel
|
|
14
14
|
# should not require anything. But if someone has legacy require calls around,
|
15
15
|
# they will work as expected, and in a compatible way. This feature is by now
|
16
16
|
# EXPERIMENTAL and UNDOCUMENTED.
|
17
|
-
#
|
18
|
-
# We cannot decorate with prepend + super because Kernel has already been
|
19
|
-
# included in Object, and changes in ancestors don't get propagated into
|
20
|
-
# already existing ancestor chains on Ruby < 3.0.
|
21
17
|
alias_method :zeitwerk_original_require, :require
|
22
18
|
class << self
|
23
19
|
alias_method :zeitwerk_original_require, :require
|
@@ -164,13 +164,13 @@ module Zeitwerk::Loader::EagerLoad
|
|
164
164
|
log("eager load directory #{dir} start") if logger
|
165
165
|
|
166
166
|
queue = [[dir, namespace]]
|
167
|
-
|
168
|
-
dir, namespace =
|
167
|
+
until queue.empty?
|
168
|
+
dir, namespace = queue.shift
|
169
169
|
|
170
|
-
ls(dir) do |basename, abspath|
|
170
|
+
ls(dir) do |basename, abspath, ftype|
|
171
171
|
next if honour_exclusions && eager_load_exclusions.member?(abspath)
|
172
172
|
|
173
|
-
if
|
173
|
+
if ftype == :file
|
174
174
|
if (cref = autoloads[abspath])
|
175
175
|
cget(*cref)
|
176
176
|
end
|
@@ -209,9 +209,9 @@ module Zeitwerk::Loader::EagerLoad
|
|
209
209
|
next_dirs = []
|
210
210
|
|
211
211
|
suffix.split("::").each do |segment|
|
212
|
-
while dir = dirs.shift
|
213
|
-
ls(dir) do |basename, abspath|
|
214
|
-
next unless
|
212
|
+
while (dir = dirs.shift)
|
213
|
+
ls(dir) do |basename, abspath, ftype|
|
214
|
+
next unless ftype == :directory
|
215
215
|
|
216
216
|
if collapse?(abspath)
|
217
217
|
dirs << abspath
|
@@ -31,26 +31,39 @@ module Zeitwerk::Loader::Helpers
|
|
31
31
|
if dir?(abspath)
|
32
32
|
next if roots.key?(abspath)
|
33
33
|
next if !has_at_least_one_ruby_file?(abspath)
|
34
|
+
ftype = :directory
|
34
35
|
else
|
35
36
|
next unless ruby?(abspath)
|
37
|
+
ftype = :file
|
36
38
|
end
|
37
39
|
|
38
40
|
# We freeze abspath because that saves allocations when passed later to
|
39
41
|
# File methods. See #125.
|
40
|
-
yield basename, abspath.freeze
|
42
|
+
yield basename, abspath.freeze, ftype
|
41
43
|
end
|
42
44
|
end
|
43
45
|
|
46
|
+
# Looks for a Ruby file using breadth-first search. This type of search is
|
47
|
+
# important to list as less directories as possible and return fast in the
|
48
|
+
# common case in which there are Ruby files.
|
49
|
+
#
|
44
50
|
# @sig (String) -> bool
|
45
51
|
private def has_at_least_one_ruby_file?(dir)
|
46
52
|
to_visit = [dir]
|
47
53
|
|
48
|
-
while dir = to_visit.shift
|
49
|
-
|
54
|
+
while (dir = to_visit.shift)
|
55
|
+
children = Dir.children(dir)
|
56
|
+
|
57
|
+
children.each do |basename|
|
58
|
+
next if hidden?(basename)
|
59
|
+
|
60
|
+
abspath = File.join(dir, basename)
|
61
|
+
next if ignored_path?(abspath)
|
62
|
+
|
50
63
|
if dir?(abspath)
|
51
|
-
to_visit << abspath
|
64
|
+
to_visit << abspath unless roots.key?(abspath)
|
52
65
|
else
|
53
|
-
return true
|
66
|
+
return true if ruby?(abspath)
|
54
67
|
end
|
55
68
|
end
|
56
69
|
end
|
data/lib/zeitwerk/loader.rb
CHANGED
@@ -230,53 +230,87 @@ module Zeitwerk
|
|
230
230
|
setup
|
231
231
|
end
|
232
232
|
|
233
|
-
|
234
|
-
|
235
|
-
|
233
|
+
# Returns a hash that maps the absolute paths of the managed files and
|
234
|
+
# directories to their respective expected constant paths.
|
235
|
+
#
|
236
|
+
# @sig () -> Hash[String, String]
|
237
|
+
def all_expected_cpaths
|
238
|
+
result = {}
|
236
239
|
|
237
|
-
|
240
|
+
actual_roots.each do |root_dir, root_namespace|
|
241
|
+
queue = [[root_dir, real_mod_name(root_namespace)]]
|
238
242
|
|
239
|
-
|
240
|
-
|
243
|
+
until queue.empty?
|
244
|
+
dir, cpath = queue.shift
|
245
|
+
result[dir] = cpath
|
241
246
|
|
242
|
-
|
247
|
+
prefix = cpath == "Object" ? "" : cpath + "::"
|
243
248
|
|
244
|
-
|
245
|
-
|
246
|
-
|
249
|
+
ls(dir) do |basename, abspath, ftype|
|
250
|
+
if ftype == :file
|
251
|
+
basename.delete_suffix!(".rb")
|
252
|
+
result[abspath] = prefix + inflector.camelize(basename, abspath)
|
253
|
+
else
|
254
|
+
if collapse?(abspath)
|
255
|
+
queue << [abspath, cpath]
|
256
|
+
else
|
257
|
+
queue << [abspath, prefix + inflector.camelize(basename, abspath)]
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
247
263
|
|
248
|
-
|
249
|
-
walk_up_from = File.dirname(abspath)
|
250
|
-
else
|
251
|
-
walk_up_from = abspath
|
264
|
+
result
|
252
265
|
end
|
253
266
|
|
254
|
-
|
267
|
+
# @sig (String | Pathname) -> String?
|
268
|
+
def cpath_expected_at(path)
|
269
|
+
abspath = File.expand_path(path)
|
255
270
|
|
256
|
-
|
257
|
-
break if root_namespace = roots[dir]
|
258
|
-
return if ignored_path?(dir)
|
271
|
+
raise Zeitwerk::Error.new("#{abspath} does not exist") unless File.exist?(abspath)
|
259
272
|
|
260
|
-
|
261
|
-
return if
|
273
|
+
return unless dir?(abspath) || ruby?(abspath)
|
274
|
+
return if ignored_path?(abspath)
|
262
275
|
|
263
|
-
paths
|
264
|
-
end
|
276
|
+
paths = []
|
265
277
|
|
266
|
-
|
278
|
+
if ruby?(abspath)
|
279
|
+
basename = File.basename(abspath, ".rb")
|
280
|
+
return if hidden?(basename)
|
267
281
|
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
282
|
+
paths << [basename, abspath]
|
283
|
+
walk_up_from = File.dirname(abspath)
|
284
|
+
else
|
285
|
+
walk_up_from = abspath
|
286
|
+
end
|
272
287
|
|
273
|
-
|
274
|
-
|
288
|
+
root_namespace = nil
|
289
|
+
|
290
|
+
walk_up(walk_up_from) do |dir|
|
291
|
+
break if root_namespace = roots[dir]
|
292
|
+
return if ignored_path?(dir)
|
293
|
+
|
294
|
+
basename = File.basename(dir)
|
295
|
+
return if hidden?(basename)
|
296
|
+
|
297
|
+
paths << [basename, abspath] unless collapse?(dir)
|
298
|
+
end
|
299
|
+
|
300
|
+
return unless root_namespace
|
301
|
+
|
302
|
+
if paths.empty?
|
303
|
+
real_mod_name(root_namespace)
|
275
304
|
else
|
276
|
-
|
305
|
+
cnames = paths.reverse_each.map { |b, a| cname_for(b, a) }
|
306
|
+
|
307
|
+
if root_namespace == Object
|
308
|
+
cnames.join("::")
|
309
|
+
else
|
310
|
+
"#{real_mod_name(root_namespace)}::#{cnames.join("::")}"
|
311
|
+
end
|
277
312
|
end
|
278
313
|
end
|
279
|
-
end
|
280
314
|
|
281
315
|
# Says if the given constant path would be unloaded on reload. This
|
282
316
|
# predicate returns `false` if reloading is disabled.
|
@@ -408,8 +442,8 @@ module Zeitwerk
|
|
408
442
|
|
409
443
|
# @sig (String, Module) -> void
|
410
444
|
private def define_autoloads_for_dir(dir, parent)
|
411
|
-
ls(dir) do |basename, abspath|
|
412
|
-
if
|
445
|
+
ls(dir) do |basename, abspath, ftype|
|
446
|
+
if ftype == :file
|
413
447
|
basename.delete_suffix!(".rb")
|
414
448
|
autoload_file(parent, cname_for(basename, abspath), abspath)
|
415
449
|
else
|
data/lib/zeitwerk/version.rb
CHANGED
data/lib/zeitwerk.rb
CHANGED
@@ -9,6 +9,7 @@ module Zeitwerk
|
|
9
9
|
require_relative "zeitwerk/explicit_namespace"
|
10
10
|
require_relative "zeitwerk/inflector"
|
11
11
|
require_relative "zeitwerk/gem_inflector"
|
12
|
+
require_relative "zeitwerk/null_inflector"
|
12
13
|
require_relative "zeitwerk/kernel"
|
13
14
|
require_relative "zeitwerk/error"
|
14
15
|
require_relative "zeitwerk/version"
|
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.6.
|
4
|
+
version: 2.6.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Xavier Noria
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-05-26 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |2
|
14
14
|
Zeitwerk implements constant autoloading with Ruby semantics. Each gem
|
@@ -35,6 +35,7 @@ files:
|
|
35
35
|
- lib/zeitwerk/loader/config.rb
|
36
36
|
- lib/zeitwerk/loader/eager_load.rb
|
37
37
|
- lib/zeitwerk/loader/helpers.rb
|
38
|
+
- lib/zeitwerk/null_inflector.rb
|
38
39
|
- lib/zeitwerk/real_mod_name.rb
|
39
40
|
- lib/zeitwerk/registry.rb
|
40
41
|
- lib/zeitwerk/version.rb
|
@@ -61,7 +62,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
61
62
|
- !ruby/object:Gem::Version
|
62
63
|
version: '0'
|
63
64
|
requirements: []
|
64
|
-
rubygems_version: 3.
|
65
|
+
rubygems_version: 3.5.7
|
65
66
|
signing_key:
|
66
67
|
specification_version: 4
|
67
68
|
summary: Efficient and thread-safe constant autoloader
|