im 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +28 -31
- data/lib/im/loader.rb +1 -1
- data/lib/im/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e1708fffea9fb79c809dbfa34669e5471556e4d969ae8d95e689cfccc5c6f3e4
|
4
|
+
data.tar.gz: bce10f72bc879a53bda624ced7534bd0c74fc5666c6ff8545ea9371521edc8b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a112f1ee72916d690c0227a94a16f87d283b93a059f1e01d8681649ac9405ce46add46650234b2e337ace8b8571c64ba4f722f256099263eea04cfaafb3f02e1
|
7
|
+
data.tar.gz: b7a03df97bcbac97f09c8637f9c8b82fbaaddcd58640aecc2406e821910fe5cb2ed4200ddc2d6490bc0d0d2d42e6a65173bb7a52ba78c7ed2c05126a0edc669b
|
data/README.md
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
# Im
|
2
2
|
|
3
|
+
[][gem]
|
3
4
|
[][actions]
|
4
5
|
|
6
|
+
[gem]: https://rubygems.org/gems/im
|
5
7
|
[actions]: https://github.com/shioyama/im/actions
|
6
8
|
|
7
9
|
<!-- TOC -->
|
@@ -28,13 +30,12 @@ any way touching the global namespace.
|
|
28
30
|
To do this, Im leverages code autoloading, Zeitwerk conventions around file
|
29
31
|
structure and naming, and two features added in Ruby 3.2: `Kernel#load`
|
30
32
|
with a module argument[^1] and `Module#const_added`[^2]. Since these Ruby
|
31
|
-
features are essential to its design,
|
33
|
+
features are essential to its design, Im is not usable with earlier versions
|
32
34
|
of Ruby.
|
33
35
|
|
34
|
-
Im started its life as a fork of Zeitwerk and has a very similar interface.
|
35
|
-
|
36
|
-
|
37
|
-
paths managed by each gem.
|
36
|
+
Im started its life as a fork of Zeitwerk and has a very similar interface. Im
|
37
|
+
and Zeitwerk can be used alongside each other provided there is no overlap
|
38
|
+
between file paths managed by each gem.
|
38
39
|
|
39
40
|
Im is in active development and should be considered experimental until the
|
40
41
|
eventual release of version 1.0. Versions 0.1.6 and earlier of the gem were
|
@@ -43,12 +44,12 @@ part of a different experiment and are unrelated to the current gem.
|
|
43
44
|
<a id="markdown-synopsis" name="synopsis"></a>
|
44
45
|
## Synopsis
|
45
46
|
|
46
|
-
Im
|
47
|
-
|
47
|
+
Im's public interface is in most respects identical to that of Zeitwerk. The
|
48
|
+
central difference is that whereas Zeitwerk loads constants into the global
|
48
49
|
namespace (rooted in `Object`), Im loads them into anonymous namespaces rooted
|
49
|
-
on the loader itself.
|
50
|
-
|
51
|
-
loaders, there can also be arbitrarily many autoloaded namespaces.
|
50
|
+
on the loader itself. `Im::Loader` is a subclass of `Module`, and thus each
|
51
|
+
loader instance can define its own namespace. Since there can be arbitrarily
|
52
|
+
many loaders, there can also be arbitrarily many autoloaded namespaces.
|
52
53
|
|
53
54
|
Im's gem interface looks like this:
|
54
55
|
|
@@ -66,7 +67,7 @@ end
|
|
66
67
|
loader.eager_load # optionally
|
67
68
|
```
|
68
69
|
|
69
|
-
The generic interface is
|
70
|
+
The generic interface is identical to Zeitwerk's:
|
70
71
|
|
71
72
|
```ruby
|
72
73
|
loader = Zeitwerk::Loader.new
|
@@ -84,7 +85,7 @@ Object.const_defined?(:MyGem)
|
|
84
85
|
```
|
85
86
|
|
86
87
|
In order to prevent leakage, the gem's entrypoint, in this case
|
87
|
-
`lib/my_gem.rb
|
88
|
+
`lib/my_gem.rb`, must not define anything at toplevel, hence the use of
|
88
89
|
`module loader::MyGem`.
|
89
90
|
|
90
91
|
Once the entrypoint has been required, all constants defined within the gem's
|
@@ -107,7 +108,7 @@ foo = loader::MyGem::Foo
|
|
107
108
|
# loads `Foo` from lib/my_gem/foo.rb
|
108
109
|
|
109
110
|
foo.new.hello_world
|
110
|
-
|
111
|
+
#=> "Hello World!"
|
111
112
|
```
|
112
113
|
|
113
114
|
Constants under the loader can be given permanent names that are different from
|
@@ -116,16 +117,12 @@ the one defined in the gem itself:
|
|
116
117
|
```ruby
|
117
118
|
Bar = loader::MyGem::Foo
|
118
119
|
Bar.new.hello_world
|
119
|
-
|
120
|
+
#=> "Hello World!"
|
120
121
|
```
|
121
122
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
The loader variable can go out of scope. Like Zeitwerk, Im keeps a registry
|
126
|
-
with all of them, and so the object won't be garbage collected. For
|
127
|
-
convenience, Im also provides a method, `Im#import`, to fetch a loader for
|
128
|
-
a given file path:
|
123
|
+
Like Zeitwerk, Im keeps a registry of all loaders, so the loader objects won't
|
124
|
+
be garbage collected. For convenience, Im also provides a method, `Im#import`,
|
125
|
+
to fetch a loader for a given file path:
|
129
126
|
|
130
127
|
```ruby
|
131
128
|
require "im"
|
@@ -133,7 +130,7 @@ require "my_gem"
|
|
133
130
|
|
134
131
|
extend Im
|
135
132
|
my_gem = import "my_gem"
|
136
|
-
#=>
|
133
|
+
#=> my_gem::MyGem is autoloadable
|
137
134
|
```
|
138
135
|
|
139
136
|
Reloading works like Zeitwerk:
|
@@ -209,15 +206,15 @@ anywhere in the global namespace.
|
|
209
206
|
### Relative and absolute cpaths
|
210
207
|
|
211
208
|
Im uses two types of constant paths: relative and absolute, wherever possible
|
212
|
-
defaulting to relative ones. A
|
209
|
+
defaulting to relative ones. A _relative cpath_ is a constant name relative to
|
213
210
|
the loader in which it was originally defined, regardless of any other names it
|
214
|
-
was assigned. Whereas Zeitwerk uses absolute cpaths, Im uses relative
|
215
|
-
all external loader APIs (see usage for examples).
|
211
|
+
was later assigned. Whereas Zeitwerk uses absolute cpaths, Im uses relative
|
212
|
+
cpaths for all external loader APIs (see usage for examples).
|
216
213
|
|
217
214
|
To understand these concepts, it is important first to distinguish between two
|
218
215
|
types of names in Ruby: _temporary names_ and _permanent names_.
|
219
216
|
|
220
|
-
A
|
217
|
+
A _temporary name_ is a constant name on an anonymous-rooted namespace, for
|
221
218
|
example a loader:
|
222
219
|
|
223
220
|
```ruby
|
@@ -228,7 +225,7 @@ my_gem::Foo.name
|
|
228
225
|
```
|
229
226
|
|
230
227
|
Here, the string `"#<Im::Loader ...>::Foo"` is called a temporary name. We can
|
231
|
-
give this module a
|
228
|
+
give this module a _permanent name_ by assigning it to a toplevel constant:
|
232
229
|
|
233
230
|
```ruby
|
234
231
|
Bar = my_gem::Foo
|
@@ -244,12 +241,12 @@ keys in Im's internal registries to index constants and their autoloads, which
|
|
244
241
|
is critical for successful autoloading.
|
245
242
|
|
246
243
|
To get around this issue, Im tracks all module names and uses relative naming
|
247
|
-
inside loader code.
|
248
|
-
|
244
|
+
inside loader code. Internally, Im has a method, `relative_cpath`, which can
|
245
|
+
generate any module name under a module in the loader namespace:
|
249
246
|
|
250
247
|
```ruby
|
251
|
-
my_gem.relative_cpath
|
252
|
-
#=> "Foo"
|
248
|
+
my_gem.send(:relative_cpath, loader::Foo, :Baz)
|
249
|
+
#=> "Foo::Baz"
|
253
250
|
```
|
254
251
|
|
255
252
|
Using relative cpaths frees Im from depending on `Module#name` for
|
data/lib/im/loader.rb
CHANGED
@@ -390,7 +390,7 @@ module Im
|
|
390
390
|
def autoload_subdir(parent, cname, subdir)
|
391
391
|
if autoload_path = autoload_path_set_by_me_for?(parent, cname)
|
392
392
|
absolute_cpath = cpath(parent, cname)
|
393
|
-
relative_cpath = relative_cpath(
|
393
|
+
relative_cpath = relative_cpath(absolute_cpath, cname)
|
394
394
|
register_explicit_namespace(cpath, relative_cpath) if ruby?(autoload_path)
|
395
395
|
|
396
396
|
# We do not need to issue another autoload, the existing one is enough
|
data/lib/im/version.rb
CHANGED