zeitwerk 2.2.1 → 2.2.2

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: b7d5a0f54405ad45dd6afc9bf54bde579f66a75fb142cdbbfb5476157dd75493
4
- data.tar.gz: b81311bb19c3b699a6720a3bb3d6df503b858a439c5f1f2605e029117de36bcb
3
+ metadata.gz: b6e1f64abc085125dd45f5c8373d793417811074dcb1d5c655c915ad393d0cf5
4
+ data.tar.gz: b4eba128f5267c2b3f40fdcd03085faae0a9063ef3a352f18b1bdbfd3031f068
5
5
  SHA512:
6
- metadata.gz: 4f6fd6e8f7bd479ca6935d1f57d065151aff3be6977ad068f6b4ecdce200bbd131f4db4f2cc1bc2a719cb332b538cf24be55eb936a51572ac5c06676d21763f2
7
- data.tar.gz: d4266c65e380b356ff4df7394f2f1882f72ac32b5226dedd717f6b4064c8ac1b8fd3d70ec08b6f9838debfc3690d2f3eee2d6885e446f087a686a619c872c718
6
+ metadata.gz: 6928afbdf70077641fd07240ec8b22d4589e721fe0ab4a4008d3a880bf460b3daac3b7504151eae2320b98a55bd2e7cae3977c78d3dbfde156eca69270795362
7
+ data.tar.gz: b64df779dcb21d094d87ee739291e7798942262b05ff32ebd841dd33b237addf7551ff641fb5e4fd8d10ccdf54f25845e77860d68931e0ebf307164c5ce076fb
data/README.md CHANGED
@@ -15,8 +15,9 @@
15
15
  - [Nested root directories](#nested-root-directories)
16
16
  - [Usage](#usage)
17
17
  - [Setup](#setup)
18
- - [Reloading](#reloading)
18
+ - [Autoloading](#autoloading)
19
19
  - [Eager loading](#eager-loading)
20
+ - [Reloading](#reloading)
20
21
  - [Inflection](#inflection)
21
22
  - [Zeitwerk::Inflector](#zeitwerkinflector)
22
23
  - [Zeitwerk::GemInflector](#zeitwerkgeminflector)
@@ -219,33 +220,28 @@ end
219
220
 
220
221
  Zeitwerk works internally only with absolute paths to avoid costly file searches in `$LOAD_PATH`. Indeed, the root directories do not even need to belong to `$LOAD_PATH`, everything just works by design if they don't.
221
222
 
222
- <a id="markdown-reloading" name="reloading"></a>
223
- ### Reloading
223
+ <a id="markdown-autoloading" name="autoloading"></a>
224
+ ### Autoloading
224
225
 
225
- Zeitwerk is able to reload code, but you need to enable this feature:
226
+ After `setup`, you are able to reference classes and modules from the project without issuing `require` calls for them. They are all available everywhere, autoloading loads them on demand. This works even if the reference to the class or module is first hit in client code, outside your project.
226
227
 
227
- ```ruby
228
- loader = Zeitwerk::Loader.new
229
- loader.push_dir(...)
230
- loader.enable_reloading # you need to opt-in before setup
231
- loader.setup
232
- ...
233
- loader.reload
234
- ```
235
-
236
- There is no way to undo this, either you want to reload or you don't.
228
+ Let's revisit the example above:
237
229
 
238
- Enabling reloading after setup raises `Zeitwerk::Error`. Similarly, calling `reload` without having enabled reloading also raises `Zeitwerk::Error`.
239
-
240
- Generally speaking, reloading is useful while developing running services like web applications. Gems that implement regular libraries, so to speak, or services running in testing or production environments, won't normally have a use case for reloading. If reloading is not enabled, Zeitwerk is able to use less memory.
230
+ ```ruby
231
+ # lib/my_gem.rb (main file)
241
232
 
242
- Reloading removes the currently loaded classes and modules and resets the loader so that it will pick whatever is in the file system now.
233
+ require "zeitwerk"
234
+ loader = Zeitwerk::Loader.for_gem
235
+ loader.setup
243
236
 
244
- It is important to highlight that this is an instance method. Don't worry about project dependencies managed by Zeitwerk, their loaders are independent.
237
+ module MyGem
238
+ include MyLogger # (*)
239
+ end
240
+ ```
245
241
 
246
- In order for reloading to be thread-safe, you need to implement some coordination. For example, a web framework that serves each request with its own thread may have a globally accessible RW lock. When a request comes in, the framework acquires the lock for reading at the beginning, and the code in the framework that calls `loader.reload` needs to acquire the lock for writing.
242
+ That works, and there is no `require "my_gem/my_logger"`. When `(*)` is reached, Zeitwerk seamlessly autoloads `MyGem::MyLogger`.
247
243
 
248
- On reloading, client code has to update anything that would otherwise be storing a stale object. For example, if the routing layer of a web framework stores controller class objects or instances in internal structures, on reload it has to refresh them somehow, possibly reevaluating routes.
244
+ If autoloading a file does not define the expected class or module, Zeitwerk raises `Zeitwerk::NameError`, which is a subclass of `NameError`.
249
245
 
250
246
  <a id="markdown-eager-loading" name="eager-loading"></a>
251
247
  ### Eager loading
@@ -269,6 +265,8 @@ In gems, the method needs to be invoked after the main namespace has been define
269
265
 
270
266
  Eager loading is synchronized and idempotent.
271
267
 
268
+ If eager loading a file does not define the expected class or module, Zeitwerk raises `Zeitwerk::NameError`, which is a subclass of `NameError`.
269
+
272
270
  If you want to eager load yourself and all dependencies using Zeitwerk, you can broadcast the `eager_load` call to all instances:
273
271
 
274
272
  ```ruby
@@ -279,6 +277,34 @@ This may be handy in top-level services, like web applications.
279
277
 
280
278
  Note that thanks to idempotence `Zeitwerk::Loader.eager_load_all` won't eager load twice if any of the instances already eager loaded.
281
279
 
280
+ <a id="markdown-reloading" name="reloading"></a>
281
+ ### Reloading
282
+
283
+ Zeitwerk is able to reload code, but you need to enable this feature:
284
+
285
+ ```ruby
286
+ loader = Zeitwerk::Loader.new
287
+ loader.push_dir(...)
288
+ loader.enable_reloading # you need to opt-in before setup
289
+ loader.setup
290
+ ...
291
+ loader.reload
292
+ ```
293
+
294
+ There is no way to undo this, either you want to reload or you don't.
295
+
296
+ Enabling reloading after setup raises `Zeitwerk::Error`. Attempting to reload without having it enabled raises `Zeitwerk::ReloadingDisabledError`.
297
+
298
+ Generally speaking, reloading is useful while developing running services like web applications. Gems that implement regular libraries, so to speak, or services running in testing or production environments, won't normally have a use case for reloading. If reloading is not enabled, Zeitwerk is able to use less memory.
299
+
300
+ Reloading removes the currently loaded classes and modules and resets the loader so that it will pick whatever is in the file system now.
301
+
302
+ It is important to highlight that this is an instance method. Don't worry about project dependencies managed by Zeitwerk, their loaders are independent.
303
+
304
+ In order for reloading to be thread-safe, you need to implement some coordination. For example, a web framework that serves each request with its own thread may have a globally accessible RW lock. When a request comes in, the framework acquires the lock for reading at the beginning, and the code in the framework that calls `loader.reload` needs to acquire the lock for writing.
305
+
306
+ On reloading, client code has to update anything that would otherwise be storing a stale object. For example, if the routing layer of a web framework stores controller class objects or instances in internal structures, on reload it has to refresh them somehow, possibly reevaluating routes.
307
+
282
308
  <a id="markdown-inflection" name="inflection"></a>
283
309
  ### Inflection
284
310
 
@@ -494,7 +494,7 @@ module Zeitwerk
494
494
  rescue ::NameError => error
495
495
  path_type = ruby?(abspath) ? "file" : "directory"
496
496
 
497
- raise NameError, <<~MESSAGE
497
+ raise NameError.new(<<~MESSAGE, error.name)
498
498
  #{error.message} inferred by #{inflector.class} from #{path_type}
499
499
 
500
500
  #{abspath}
@@ -558,7 +558,7 @@ module Zeitwerk
558
558
  end
559
559
 
560
560
  # @param dir [String] directory that would have autovivified a module
561
- # @param file [String] the file where the namespace is explictly defined
561
+ # @param file [String] the file where the namespace is explicitly defined
562
562
  # @param parent [Module]
563
563
  # @param cname [Symbol]
564
564
  # @return [void]
@@ -14,7 +14,7 @@ module Zeitwerk::Loader::Callbacks
14
14
  if logger && cdef?(*cref)
15
15
  log("constant #{cpath(*cref)} loaded from file #{file}")
16
16
  elsif !cdef?(*cref)
17
- raise Zeitwerk::NameError, "expected file #{file} to define constant #{cpath(*cref)}, but didn't"
17
+ raise Zeitwerk::NameError.new("expected file #{file} to define constant #{cpath(*cref)}, but didn't", cref.last)
18
18
  end
19
19
  end
20
20
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Zeitwerk
4
- VERSION = "2.2.1"
4
+ VERSION = "2.2.2"
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.1
4
+ version: 2.2.2
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-01 00:00:00.000000000 Z
11
+ date: 2019-11-29 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |2
14
14
  Zeitwerk implements constant autoloading with Ruby semantics. Each gem