infusible 3.1.0 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/README.adoc +12 -12
- data/infusible.gemspec +1 -1
- data/lib/infusible/constructor.rb +13 -8
- data.tar.gz.sig +0 -0
- metadata +3 -3
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6dc14ad940c37db70d202e1c536e89308476388dafb228c79c10632688ae1f80
|
4
|
+
data.tar.gz: 62a63f85a1bad5e32dcf76945705d87cc2ea705c337f9f047473987992d4bfff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc043d373809d1f649d32d8ed5f0e4f993511c575125f9e02843e7a81f83b5e13bcf15e7ff070866a88a9ffa2b935d1eeb5e7ec961a2f3d9b73b660c6ffce5fe
|
7
|
+
data.tar.gz: 47006245798afea15ba7e440b2c71f8925cbbd649cc0fdb0785612aa7b6716d98bc11cee3bfd720be3c310307ad3a50c7b1d37bf7f3632ffa2cfe4a058176943
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/README.adoc
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
|
11
11
|
Automatically injects dependencies within your object via the _Dependency Inversion Principle_ -- the _D_ in _SOLID_ design -- and is a powerful way to compose complex architectures from small objects which leverage the _Single Responsibility Principle_ -- the _S_ in _SOLID_ design.
|
12
12
|
|
13
|
-
|
13
|
+
When coupled with {dependency_injection_containers_link}, as provided by the {dry-container_link} gem, Infusible completes the second half of the _Dependency Inversion Principle_. Here's a quick example of Infusible in action:
|
14
14
|
|
15
15
|
[source,ruby]
|
16
16
|
----
|
@@ -73,7 +73,7 @@ require "infusible"
|
|
73
73
|
|
74
74
|
== Usage
|
75
75
|
|
76
|
-
There is basic and advanced usage. We'll start with
|
76
|
+
There is basic and advanced usage. We'll start with the basics and work our to more advanced usage.
|
77
77
|
|
78
78
|
=== Basic
|
79
79
|
|
@@ -81,7 +81,7 @@ This gem requires three steps for proper use:
|
|
81
81
|
|
82
82
|
. A container.
|
83
83
|
. An import constant.
|
84
|
-
.
|
84
|
+
. An object and/or multiple objects for dependencies to be injected into.
|
85
85
|
|
86
86
|
Let's walk through each staring by defining a container of dependencies.
|
87
87
|
|
@@ -238,7 +238,7 @@ class Pinger
|
|
238
238
|
end
|
239
239
|
----
|
240
240
|
|
241
|
-
The above will ensure the logger gets passed upwards to the superclass while remaining accessible by subclass.
|
241
|
+
The above will ensure the logger gets passed upwards to the superclass while remaining accessible by the subclass.
|
242
242
|
|
243
243
|
==== Inheritance
|
244
244
|
|
@@ -289,7 +289,7 @@ end
|
|
289
289
|
|
290
290
|
With the above, the child class will have access to both the `logger` and `http` dependencies.
|
291
291
|
|
292
|
-
⚠️ Be careful when using parent dependencies within your child classes since they are _private by default_. Even though you can reach them, they might change, which can break your downstream dependencies and probably should be avoided or at least defined as `protected` by your parent objects in order to avoid breaking
|
292
|
+
⚠️ Be careful when using parent dependencies within your child classes since they are _private by default_. Even though you can reach them, they might change, which can break your downstream dependencies and probably should be avoided or at least defined as `protected` by your parent objects in order to avoid breaking the parent/child relationship.
|
293
293
|
|
294
294
|
==== Scopes
|
295
295
|
|
@@ -299,7 +299,7 @@ By default -- and in all of the examples shown so far -- your dependencies are p
|
|
299
299
|
* `include Import.protected(logger)`: Injects a _protected_ logger dependency. Useful with inheritance and a subclass needs access to the dependency.
|
300
300
|
* `include Import.public(:logger)`: Injects a _public_ logger dependency.
|
301
301
|
|
302
|
-
There is no `+#private+` method since `#[]` does this for you and is
|
302
|
+
There is no `+#private+` method since `#[]` does this for you and is _recommended practice_. Use of `+#public+` and `+#protected+` should be used sparingly or not at all if you can avoid it. Here's an example where public, protected, and private dependencies are injected:
|
303
303
|
|
304
304
|
[source,ruby]
|
305
305
|
----
|
@@ -354,7 +354,7 @@ Demo.new.call
|
|
354
354
|
# Two
|
355
355
|
----
|
356
356
|
|
357
|
-
As you can see, with the _private_ `#infused_keys` attribute reader, we
|
357
|
+
As you can see, with the _private_ `#infused_keys` attribute reader, we are able to iterate through each infused key and send the `#call` message to each injected dependency.
|
358
358
|
|
359
359
|
Since `#infused_keys` is a private attribute reader, this means the infused keys are private to each instance. This includes all ancestors when using inheritance as each super class in the hierarchy will have it's own unique array of infused keys depending on what was injected for that object.
|
360
360
|
|
@@ -362,7 +362,7 @@ All infused keys are frozen by default.
|
|
362
362
|
|
363
363
|
=== Tests
|
364
364
|
|
365
|
-
As you architect your implementation, you'll want to test your injected dependencies. You
|
365
|
+
As you architect your implementation, you'll want to test your injected dependencies. You might want to stub, mock, or spy on them as well. Test support is built-in for you by only requiring the stub refinement as provided by this gem. For demonstration purposes, I'll assume you are using RSpec but you can adapt for whatever testing framework you are using.
|
366
366
|
|
367
367
|
Let's say you have the following implementation that combines both {dry-container_link} (or a primitive `Hash` would work too) and this gem:
|
368
368
|
|
@@ -415,7 +415,7 @@ RSpec.describe Action do
|
|
415
415
|
end
|
416
416
|
----
|
417
417
|
|
418
|
-
Notice
|
418
|
+
Notice there is little setup required to test the injected dependencies. You only need to use the refinement and define what you want stubbed in your `before` and `after` blocks. That's it!
|
419
419
|
|
420
420
|
While the above works great for a single spec, over time you'll want to reduce duplicated setup by using a shared context. Here's a rewrite of the above spec which significantly reduces duplication when needing to test multiple objects using the same dependencies:
|
421
421
|
|
@@ -487,7 +487,7 @@ bin/console
|
|
487
487
|
|
488
488
|
=== Architecture
|
489
489
|
|
490
|
-
This gem automates a lot of the boilerplate code you'd
|
490
|
+
This gem automates a lot of the boilerplate code you'd manually do by defining your constructor, initializer, and instance variables for you. Normally, when injecting dependencies, you'd do something like this (using the `Pinger` example provided earlier):
|
491
491
|
|
492
492
|
[source,ruby]
|
493
493
|
----
|
@@ -527,10 +527,10 @@ Your constructor, initializer, and instance variables are all there. Only you do
|
|
527
527
|
When using this gem, along with a container like {dry-container_link}, make sure to adhere to the following guidelines:
|
528
528
|
|
529
529
|
* Use containers to group related dependencies that make logical sense for the namespace you are working in and avoid using containers as a junk drawer for throwing random objects in.
|
530
|
-
* Use containers that don't have a lot of registered dependencies. If you register too many dependencies,
|
530
|
+
* Use containers that don't have a lot of registered dependencies. If you register too many dependencies, that means your objects are too complex and need to be simplified further.
|
531
531
|
* Use the `Import` constant to define _what_ is possible to import much like you'd use a `Container` to define your dependencies. Defining what is importable improves performance and should be defined in separate files for improved fuzzy file finding.
|
532
532
|
* Use `**` to forward keyword arguments when defining an initializer which needs to pass injected dependencies upwards.
|
533
|
-
* Prefer `Import#[]` over the use of `Import#public` and/or `Import#protected` as much as a possible since injected dependencies should be private, by default, in order to not break encapsulation. That said, there are times where making them public and/or protected can save you from writing
|
533
|
+
* Prefer `Import#[]` over the use of `Import#public` and/or `Import#protected` as much as a possible since injected dependencies should be private, by default, in order to not break encapsulation. That said, there are times where making them public and/or protected can save you from writing boilerplate code.
|
534
534
|
|
535
535
|
== Tests
|
536
536
|
|
data/infusible.gemspec
CHANGED
@@ -30,20 +30,25 @@ module Infusible
|
|
30
30
|
@instance_module = Class.new(Module).new
|
31
31
|
end
|
32
32
|
|
33
|
-
def included
|
33
|
+
def included descendant
|
34
|
+
unless descendant.is_a? Class
|
35
|
+
fail TypeError,
|
36
|
+
"Can only infuse a class, invalid object: #{descendant} (#{descendant.class})."
|
37
|
+
end
|
38
|
+
|
34
39
|
super
|
35
|
-
define
|
36
|
-
|
37
|
-
|
40
|
+
define descendant
|
41
|
+
descendant.extend class_module
|
42
|
+
descendant.include instance_module
|
38
43
|
end
|
39
44
|
|
40
45
|
private
|
41
46
|
|
42
47
|
attr_reader :container, :dependencies, :scope, :class_module, :instance_module
|
43
48
|
|
44
|
-
def define
|
49
|
+
def define descendant
|
45
50
|
define_new
|
46
|
-
define_initialize
|
51
|
+
define_initialize descendant
|
47
52
|
define_readers
|
48
53
|
end
|
49
54
|
|
@@ -56,8 +61,8 @@ module Infusible
|
|
56
61
|
end
|
57
62
|
end
|
58
63
|
|
59
|
-
def define_initialize
|
60
|
-
super_parameters = Marameters.of(
|
64
|
+
def define_initialize descendant
|
65
|
+
super_parameters = Marameters.of(descendant, :initialize).map do |instance|
|
61
66
|
break instance unless instance.only_bare_splats?
|
62
67
|
end
|
63
68
|
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: infusible
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brooke Kuhlmann
|
@@ -35,7 +35,7 @@ cert_chain:
|
|
35
35
|
3n5C8/6Zh9DYTkpcwPSuIfAga6wf4nXc9m6JAw8AuMLaiWN/r/2s4zJsUHYERJEu
|
36
36
|
gZGm4JqtuSg8pYjPeIJxS960owq+SfuC+jxqmRA54BisFCv/0VOJi7tiJVY=
|
37
37
|
-----END CERTIFICATE-----
|
38
|
-
date: 2024-
|
38
|
+
date: 2024-02-18 00:00:00.000000000 Z
|
39
39
|
dependencies:
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: marameters
|
@@ -110,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
110
|
- !ruby/object:Gem::Version
|
111
111
|
version: '0'
|
112
112
|
requirements: []
|
113
|
-
rubygems_version: 3.5.
|
113
|
+
rubygems_version: 3.5.6
|
114
114
|
signing_key:
|
115
115
|
specification_version: 4
|
116
116
|
summary: An automated dependency manager and injector.
|
metadata.gz.sig
CHANGED
Binary file
|