zeitwerk 2.2.2 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b6e1f64abc085125dd45f5c8373d793417811074dcb1d5c655c915ad393d0cf5
4
- data.tar.gz: b4eba128f5267c2b3f40fdcd03085faae0a9063ef3a352f18b1bdbfd3031f068
3
+ metadata.gz: b8fd1828e8e92937af8b1e46033442f517c65c07a443a9a265b67c03f22b8b86
4
+ data.tar.gz: 4e04076d6ac82d1bff9bf3db8604ca7e826afad753fb1268116cd115f15d301b
5
5
  SHA512:
6
- metadata.gz: 6928afbdf70077641fd07240ec8b22d4589e721fe0ab4a4008d3a880bf460b3daac3b7504151eae2320b98a55bd2e7cae3977c78d3dbfde156eca69270795362
7
- data.tar.gz: b64df779dcb21d094d87ee739291e7798942262b05ff32ebd841dd33b237addf7551ff641fb5e4fd8d10ccdf54f25845e77860d68931e0ebf307164c5ce076fb
6
+ metadata.gz: cacd0d2c43a566a5e3be7dfb98585e9598a9fda8e930bb0f97a96180db332d6303fb1cfbf850f85dd822071968fc624262b94c27db85ad3e1236f1e243df64c2
7
+ data.tar.gz: 0f9c90d543eae10edade4777f63c02a0f5ef30ecfdfe752fc9f11e5f6e3c835d2b893b0e8074e4cd068859e41dcf6e5374527c73499876deab3a9974cd0d2bf4
data/README.md CHANGED
@@ -12,6 +12,7 @@
12
12
  - [File structure](#file-structure)
13
13
  - [Implicit namespaces](#implicit-namespaces)
14
14
  - [Explicit namespaces](#explicit-namespaces)
15
+ - [Collapsing directories](#collapsing-directories)
15
16
  - [Nested root directories](#nested-root-directories)
16
17
  - [Usage](#usage)
17
18
  - [Setup](#setup)
@@ -165,6 +166,32 @@ end
165
166
 
166
167
  An explicit namespace must be managed by one single loader. Loaders that reopen namespaces owned by other projects are responsible for loading their constants before setup.
167
168
 
169
+ <a id="markdown-collapsing-directories" name="collapsing-directories"></a>
170
+ ### Collapsing directories
171
+
172
+ Say some directories in a project exist for organizational purposes only, and you prefer not to have them as namespaces. For example, the `actions` subdirectory in the next example is not meant to represent a namespace, it is there only to group all actions related to bookings:
173
+
174
+ ```
175
+ booking.rb -> Booking
176
+ booking/actions/create.rb -> Booking::Create
177
+ ```
178
+
179
+ To make it work that way, configure Zeitwerk to collapse said directory:
180
+
181
+ ```ruby
182
+ loader.collapse("booking/actions")
183
+ ```
184
+
185
+ This method accepts an arbitrary number of strings or `Pathname` objects, and also an array of them.
186
+
187
+ You can pass directories and glob patterns. Glob patterns are expanded when they are added, and again on each reload.
188
+
189
+ To illustrate usage of glob patterns, if `actions` in the example above is part of a standardized structure, you could use a wildcard:
190
+
191
+ ```ruby
192
+ loader.collapse("*/actions")
193
+ ```
194
+
168
195
  <a id="markdown-nested-root-directories" name="nested-root-directories"></a>
169
196
  ### Nested root directories
170
197
 
@@ -39,7 +39,7 @@ module Zeitwerk
39
39
  # @return [<String>]
40
40
  attr_reader :preloads
41
41
 
42
- # Absolute paths of files, directories, of glob patterns to be totally
42
+ # Absolute paths of files, directories, or glob patterns to be totally
43
43
  # ignored.
44
44
  #
45
45
  # @private
@@ -54,6 +54,19 @@ module Zeitwerk
54
54
  # @return [Set<String>]
55
55
  attr_reader :ignored_paths
56
56
 
57
+ # Absolute paths of directories or glob patterns to be collapsed.
58
+ #
59
+ # @private
60
+ # @return [Set<String>]
61
+ attr_reader :collapse_glob_patterns
62
+
63
+ # The actual collection of absolute directory names at the time the collapse
64
+ # glob patterns were expanded. Computed on setup, and recomputed on reload.
65
+ #
66
+ # @private
67
+ # @return [Set<String>]
68
+ attr_reader :collapse_dirs
69
+
57
70
  # Maps real absolute paths for which an autoload has been set ---and not
58
71
  # executed--- to their corresponding parent class or module and constant
59
72
  # name.
@@ -131,15 +144,17 @@ module Zeitwerk
131
144
  @inflector = Inflector.new
132
145
  @logger = self.class.default_logger
133
146
 
134
- @root_dirs = {}
135
- @preloads = []
136
- @ignored_glob_patterns = Set.new
137
- @ignored_paths = Set.new
138
- @autoloads = {}
139
- @autoloaded_dirs = []
140
- @to_unload = {}
141
- @lazy_subdirs = {}
142
- @eager_load_exclusions = Set.new
147
+ @root_dirs = {}
148
+ @preloads = []
149
+ @ignored_glob_patterns = Set.new
150
+ @ignored_paths = Set.new
151
+ @collapse_glob_patterns = Set.new
152
+ @collapse_dirs = Set.new
153
+ @autoloads = {}
154
+ @autoloaded_dirs = []
155
+ @to_unload = {}
156
+ @lazy_subdirs = {}
157
+ @eager_load_exclusions = Set.new
143
158
 
144
159
  # TODO: find a better name for these mutexes.
145
160
  @mutex = Mutex.new
@@ -154,6 +169,7 @@ module Zeitwerk
154
169
 
155
170
  # Sets a tag for the loader, useful for logging.
156
171
  #
172
+ # @param tag [#to_s]
157
173
  # @return [void]
158
174
  def tag=(tag)
159
175
  @tag = tag.to_s
@@ -233,6 +249,18 @@ module Zeitwerk
233
249
  end
234
250
  end
235
251
 
252
+ # Configure directories or glob patterns to be collapsed.
253
+ #
254
+ # @param paths [<String, Pathname, <String, Pathname>>]
255
+ # @return [void]
256
+ def collapse(*glob_patterns)
257
+ glob_patterns = expand_paths(glob_patterns)
258
+ mutex.synchronize do
259
+ collapse_glob_patterns.merge(glob_patterns)
260
+ collapse_dirs.merge(expand_glob_patterns(glob_patterns))
261
+ end
262
+ end
263
+
236
264
  # Sets autoloads in the root namespace and preloads files, if any.
237
265
  #
238
266
  # @return [void]
@@ -306,7 +334,8 @@ module Zeitwerk
306
334
  Registry.on_unload(self)
307
335
  ExplicitNamespace.unregister(self)
308
336
 
309
- @setup = false
337
+ @setup = false
338
+ @eager_loaded = false
310
339
  end
311
340
  end
312
341
 
@@ -322,6 +351,7 @@ module Zeitwerk
322
351
  if reloading_enabled?
323
352
  unload
324
353
  recompute_ignored_paths
354
+ recompute_collapse_dirs
325
355
  setup
326
356
  else
327
357
  raise ReloadingDisabledError, "can't reload, please call loader.enable_reloading before setup"
@@ -351,8 +381,12 @@ module Zeitwerk
351
381
  cref[0].const_get(cref[1], false)
352
382
  end
353
383
  elsif dir?(abspath) && !root_dirs.key?(abspath)
354
- cname = inflector.camelize(basename, abspath)
355
- queue << [namespace.const_get(cname, false), abspath]
384
+ if collapse_dirs.member?(abspath)
385
+ queue << [namespace, abspath]
386
+ else
387
+ cname = inflector.camelize(basename, abspath)
388
+ queue << [namespace.const_get(cname, false), abspath]
389
+ end
356
390
  end
357
391
  end
358
392
  end
@@ -476,7 +510,7 @@ module Zeitwerk
476
510
  ls(dir) do |basename, abspath|
477
511
  begin
478
512
  if ruby?(basename)
479
- basename.slice!(-3, 3)
513
+ basename[-3..-1] = ''
480
514
  cname = inflector.camelize(basename, abspath).to_sym
481
515
  autoload_file(parent, cname, abspath)
482
516
  elsif dir?(abspath)
@@ -488,7 +522,11 @@ module Zeitwerk
488
522
  # it counts only as root. The guard checks that.
489
523
  unless root_dirs.key?(abspath)
490
524
  cname = inflector.camelize(basename, abspath).to_sym
491
- autoload_subdir(parent, cname, abspath)
525
+ if collapse_dirs.member?(abspath)
526
+ set_autoloads_in_dir(abspath, parent)
527
+ else
528
+ autoload_subdir(parent, cname, abspath)
529
+ end
492
530
  end
493
531
  end
494
532
  rescue ::NameError => error
@@ -717,6 +755,11 @@ module Zeitwerk
717
755
  ignored_paths.replace(expand_glob_patterns(ignored_glob_patterns))
718
756
  end
719
757
 
758
+ # @return [void]
759
+ def recompute_collapse_dirs
760
+ collapse_dirs.replace(expand_glob_patterns(collapse_glob_patterns))
761
+ end
762
+
720
763
  # @param message [String]
721
764
  # @return [void]
722
765
  def log(message)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Zeitwerk
4
- VERSION = "2.2.2"
4
+ VERSION = "2.3.0"
5
5
  end
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.2.2
4
+ version: 2.3.0
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-11-29 00:00:00.000000000 Z
11
+ date: 2020-03-03 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |2
14
14
  Zeitwerk implements constant autoloading with Ruby semantics. Each gem