inoculate 0.2.0 → 0.3.0
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/CHANGELOG.md +5 -0
- data/README.md +49 -0
- data/lib/inoculate/configurer.rb +12 -2
- data/lib/inoculate/manufacturer.rb +66 -21
- data/lib/inoculate/version.rb +1 -1
- data/sig/inoculate.rbs +6 -4
- 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: 2649bf406a68234451cc147c069a8b9d58ce91d2a1538e728a532ff4abda2180
|
4
|
+
data.tar.gz: 3bf808d9e35467647432ed7d74cab98e669a41f7e887e889735c8d583844eaf7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff27ab41b2f2da2cc6ebf22e434c88b626b9b0c2bf6dab505a9baa1a777faf82c60512a44bb258e19bf0ceb71315b0f0123ab724d6dcb65dfb0468d3d9cf7b35
|
7
|
+
data.tar.gz: 23212f8eeb9dc79c159651ebebc93d4ca13ad7623aa2d85622fe8de7b64f993880db5837e51a072f9116bffc169f02030b0676247f1befb254e86023443436ed
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -24,6 +24,7 @@ It provides several life-cycles and provides dependency access through private a
|
|
24
24
|
2. [Usage](#usage)
|
25
25
|
1. [Dependency Life Cycles](#dependency-life-cycles)
|
26
26
|
1. [Transient](#transient)
|
27
|
+
2. [Instance](#instance)
|
27
28
|
2. [Renaming the Declaration API](#renaming-the-declaration-api)
|
28
29
|
3. [Hide Your Dependency on Inoculate](#hide-your-dependency-on-inoculate)
|
29
30
|
3. [Installation](#installation)
|
@@ -109,6 +110,54 @@ Count is: 0
|
|
109
110
|
=> nil
|
110
111
|
```
|
111
112
|
|
113
|
+
#### Instance
|
114
|
+
Instance dependencies are constructed once for each instance of a dependent class.
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
class Counter
|
118
|
+
attr_reader :count
|
119
|
+
|
120
|
+
def initialize
|
121
|
+
@count = 0
|
122
|
+
end
|
123
|
+
|
124
|
+
def inc
|
125
|
+
@count += 1
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
Inoculate.initialize do |config|
|
130
|
+
config.instance(:counter) { Counter.new }
|
131
|
+
end
|
132
|
+
|
133
|
+
class Example
|
134
|
+
include Inoculate::Porter
|
135
|
+
inoculate_with :counter
|
136
|
+
|
137
|
+
def initialize(name)
|
138
|
+
@name = name
|
139
|
+
end
|
140
|
+
|
141
|
+
def to_s
|
142
|
+
counter.inc
|
143
|
+
"[#{@name}] Count is: #{counter.count}"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
a = Example.new("a")
|
148
|
+
b = Example.new("b")
|
149
|
+
puts a, a, b
|
150
|
+
```
|
151
|
+
|
152
|
+
This results in:
|
153
|
+
|
154
|
+
```
|
155
|
+
[a] Count is: 1
|
156
|
+
[a] Count is: 2
|
157
|
+
[b] Count is: 1
|
158
|
+
=> nil
|
159
|
+
```
|
160
|
+
|
112
161
|
### Renaming the Declaration API
|
113
162
|
The `inoculate_with` API is named to avoid immediate collisions with other modules
|
114
163
|
and code you may have. You can use it as-is, or rename it to something you see fit
|
data/lib/inoculate/configurer.rb
CHANGED
@@ -13,8 +13,18 @@ module Inoculate
|
|
13
13
|
# @see Manufacturer#transient
|
14
14
|
#
|
15
15
|
# @since 0.1.0
|
16
|
-
def transient(name,
|
17
|
-
manufacturer.transient(name,
|
16
|
+
def transient(name, &block)
|
17
|
+
manufacturer.transient(name, &block)
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
|
21
|
+
# Register an instance dependency.
|
22
|
+
# @see Manufacturer#instance
|
23
|
+
#
|
24
|
+
# @since 0.3.0
|
25
|
+
def instance(name, &block)
|
26
|
+
manufacturer.instance(name, &block)
|
27
|
+
nil
|
18
28
|
end
|
19
29
|
|
20
30
|
private
|
@@ -28,49 +28,94 @@ module Inoculate
|
|
28
28
|
# manufacturer.transient(:sha1_hasher) { Digest::SHA1.new }
|
29
29
|
#
|
30
30
|
# @example With a Proc
|
31
|
-
# manufacturer.transient(:sha1_hasher,
|
32
|
-
#
|
33
|
-
# @example With anything Callable
|
34
|
-
# class HashingBuilder
|
35
|
-
# def call = Digest::SHA1.new
|
36
|
-
# end
|
37
|
-
# manufacturer.transient(:sha1_hasher, HashingBuilder.new)
|
31
|
+
# manufacturer.transient(:sha1_hasher, &-> { Digest::SHA1.new })
|
38
32
|
#
|
39
33
|
# @param name [Symbol, #to_sym] the dependency name which will be used to access it
|
40
|
-
# @param
|
41
|
-
# @param block [Proc, nil] an alternative builder callable
|
34
|
+
# @param block [Block, Proc] a factory method to build the dependency
|
42
35
|
#
|
43
|
-
# @raise [Errors::RequiresCallable] if no
|
36
|
+
# @raise [Errors::RequiresCallable] if no block is provided
|
44
37
|
# @raise [Errors::InvalidName] if the name is not a symbol, cannot be converted to a symbol,
|
45
38
|
# or is not a valid attribute name
|
46
39
|
# @raise [Errors::AlreadyRegistered] if the name has been registered previously
|
47
40
|
#
|
48
41
|
# @since 0.1.0
|
49
|
-
def transient(name,
|
50
|
-
|
42
|
+
def transient(name, &block)
|
43
|
+
validate_dependency_name name
|
51
44
|
raise Errors::AlreadyRegistered if @registered_blueprints.has_key? name
|
52
|
-
raise Errors::RequiresCallable
|
45
|
+
raise Errors::RequiresCallable if block.nil?
|
53
46
|
|
54
47
|
blueprint_name = name.to_sym
|
55
48
|
@registered_blueprints[blueprint_name] = {
|
56
49
|
lifecycle: :transient,
|
57
|
-
|
58
|
-
accessor_module: build_module(blueprint_name, :transient,
|
50
|
+
factory: block,
|
51
|
+
accessor_module: build_module(blueprint_name, :transient, block)
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
# Register an instance dependency.
|
56
|
+
#
|
57
|
+
# An instance dependency gets created once for each instance of a dependent class.
|
58
|
+
#
|
59
|
+
# @example With a block
|
60
|
+
# manufacturer.instance(:sha1_hasher) { Digest::SHA1.new }
|
61
|
+
#
|
62
|
+
# @example With a Proc
|
63
|
+
# manufacturer.instance(:sha1_hasher, &-> { Digest::SHA1.new })
|
64
|
+
#
|
65
|
+
# @param name [Symbol, #to_sym] the dependency name which will be used to access it
|
66
|
+
# @param block [Block, Proc] a factory method to build the dependency
|
67
|
+
#
|
68
|
+
# @raise [Errors::RequiresCallable] if no block is provided
|
69
|
+
# @raise [Errors::InvalidName] if the name is not a symbol, cannot be converted to a symbol,
|
70
|
+
# or is not a valid attribute name
|
71
|
+
# @raise [Errors::AlreadyRegistered] if the name has been registered previously
|
72
|
+
#
|
73
|
+
# @since 0.3.0
|
74
|
+
def instance(name, &block)
|
75
|
+
validate_dependency_name name
|
76
|
+
raise Errors::AlreadyRegistered if @registered_blueprints.has_key? name
|
77
|
+
raise Errors::RequiresCallable if block.nil?
|
78
|
+
|
79
|
+
blueprint_name = name.to_sym
|
80
|
+
@registered_blueprints[blueprint_name] = {
|
81
|
+
lifecycle: :instance,
|
82
|
+
factory: block,
|
83
|
+
accessor_module: build_module(blueprint_name, :instance, block)
|
59
84
|
}
|
60
85
|
end
|
61
86
|
|
62
87
|
private
|
63
88
|
|
64
|
-
def build_module(name, lifecycle,
|
89
|
+
def build_module(name, lifecycle, factory)
|
65
90
|
module_name = "I#{Digest::SHA1.hexdigest(name.to_s)}"
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
91
|
+
module_body =
|
92
|
+
case lifecycle
|
93
|
+
when :transient then build_transient(name, factory)
|
94
|
+
when :instance then build_instance(name, factory)
|
95
|
+
else raise ArgumentError, "Life cycle #{lifecycle} is not valid. Something has gone very wrong."
|
96
|
+
end
|
97
|
+
|
98
|
+
Providers.module_eval { const_set(module_name, module_body) }
|
99
|
+
end
|
100
|
+
|
101
|
+
def build_transient(name, factory)
|
102
|
+
Module.new do
|
103
|
+
private define_method(name) { factory.call }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def build_instance(name, factory)
|
108
|
+
cache_variable_name = "@icache_#{Digest::SHA1.hexdigest(name.to_s)}"
|
109
|
+
Module.new do
|
110
|
+
define_method(name) do
|
111
|
+
instance_variable_set(cache_variable_name, factory.call) unless instance_variable_defined?(cache_variable_name)
|
112
|
+
instance_variable_get(cache_variable_name)
|
113
|
+
end
|
114
|
+
private name
|
70
115
|
end
|
71
116
|
end
|
72
117
|
|
73
|
-
def
|
118
|
+
def validate_dependency_name(name)
|
74
119
|
raise Errors::InvalidName, "name must be a symbol or convert to one" unless name.respond_to? :to_sym
|
75
120
|
begin
|
76
121
|
Module.new { attr_reader name }
|
data/lib/inoculate/version.rb
CHANGED
data/sig/inoculate.rbs
CHANGED
@@ -6,9 +6,9 @@ module Inoculate
|
|
6
6
|
end
|
7
7
|
|
8
8
|
type callable = ^() -> untyped
|
9
|
-
type lifecycle_name = :transient
|
9
|
+
type lifecycle_name = :transient | :instance
|
10
10
|
type builder_name = Symbol
|
11
|
-
type blueprint = { lifecycle: lifecycle_name,
|
11
|
+
type blueprint = { lifecycle: lifecycle_name, factory: callable, accessor_module: Module? }
|
12
12
|
|
13
13
|
module Errors
|
14
14
|
class Error < StandardError
|
@@ -32,13 +32,15 @@ module Inoculate
|
|
32
32
|
|
33
33
|
class Manufacturer
|
34
34
|
attr_reader registered_blueprints: Hash[builder_name, blueprint]
|
35
|
-
def transient: (builder_name | _ToSymbol
|
35
|
+
def transient: (builder_name | _ToSymbol) { () -> void } -> void
|
36
|
+
def instance: (builder_name | _ToSymbol) { () -> void } -> void
|
36
37
|
end
|
37
38
|
|
38
39
|
class Configurer
|
39
40
|
def initialize: (Manufacturer) -> void
|
40
41
|
|
41
|
-
def transient: (builder_name | _ToSymbol
|
42
|
+
def transient: (builder_name | _ToSymbol) { () -> void } -> nil
|
43
|
+
def instance: (builder_name | _ToSymbol) { () -> void } -> nil
|
42
44
|
|
43
45
|
private
|
44
46
|
|