teckel 0.8.0 → 0.10.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 +35 -7
- data/README.md +1 -2
- data/lib/teckel/chain/config.rb +20 -19
- data/lib/teckel/chain/result.rb +5 -9
- data/lib/teckel/chain/runner.rb +8 -6
- data/lib/teckel/chain.rb +16 -15
- data/lib/teckel/config.rb +15 -9
- data/lib/teckel/contracts.rb +3 -3
- data/lib/teckel/operation/config.rb +31 -28
- data/lib/teckel/operation/result.rb +12 -12
- data/lib/teckel/operation/runner.rb +1 -1
- data/lib/teckel/operation.rb +5 -5
- data/lib/teckel/result.rb +4 -4
- data/lib/teckel/version.rb +2 -1
- data/lib/teckel.rb +4 -1
- metadata +21 -56
- data/spec/chain/around_hook_spec.rb +0 -100
- data/spec/chain/default_settings_spec.rb +0 -39
- data/spec/chain/inheritance_spec.rb +0 -116
- data/spec/chain/none_input_spec.rb +0 -36
- data/spec/chain/results_spec.rb +0 -53
- data/spec/chain_spec.rb +0 -255
- data/spec/config_spec.rb +0 -26
- data/spec/doctest_helper.rb +0 -8
- data/spec/operation/config_spec.rb +0 -227
- data/spec/operation/contract_trace_spec.rb +0 -118
- data/spec/operation/default_settings_spec.rb +0 -120
- data/spec/operation/fail_on_input_spec.rb +0 -103
- data/spec/operation/inheritance_spec.rb +0 -94
- data/spec/operation/result_spec.rb +0 -49
- data/spec/operation/results_spec.rb +0 -117
- data/spec/operation_spec.rb +0 -531
- data/spec/rb27/pattern_matching_spec.rb +0 -193
- data/spec/result_spec.rb +0 -22
- data/spec/spec_helper.rb +0 -35
- data/spec/support/dry_base.rb +0 -8
- data/spec/support/fake_db.rb +0 -12
- data/spec/support/fake_models.rb +0 -20
- data/spec/teckel_spec.rb +0 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7d5501f2c908d365f035892a55463a35ca8af67f667f00c86d995570c604c2b9
|
|
4
|
+
data.tar.gz: 9100810bce08bffe1ea102d5613d8a2cca72d9a4b775247804c473bb0434bbba
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a7cdec32036460d09fcba3793eb94a33028e833a267dce8f4dedb2859b4104371f3d84d54e41e895f81c4c62a2ea5137776e7e378f6d98f6101e72cad19618c3
|
|
7
|
+
data.tar.gz: b5e1f99450292952b164bede8a3fd8d74073be39c9b6d39bd8cda33ab2c354cc5411ad1e10238b518240bf3d31d2cf61f5679c457b147ececbfdaf1fa9148798
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
## 0.10.0
|
|
4
|
+
|
|
5
|
+
- `Teckel::Operation::Result` railway methods no longer capture block into variable
|
|
6
|
+
- Internal housekeeping
|
|
7
|
+
- Add ruby 4.0 to CI
|
|
8
|
+
- Allow bundler 4 in development
|
|
9
|
+
|
|
10
|
+
## 0.9.0
|
|
11
|
+
|
|
12
|
+
- Internal housekeeping
|
|
13
|
+
- Add ruby 3.4 and 'head' to CI
|
|
14
|
+
- Ruby < 3 won't run mutation test
|
|
15
|
+
- moved to standard.rb for linting and formatting
|
|
16
|
+
- removed usage of `forwardable` in favor of explicit delegation methods
|
|
17
|
+
- renamed internal `Teckel::Config.for` to `get_or_set`
|
|
18
|
+
- renamed internal `Teckel::Operation::Config.get_set_constructor` to `get_or_set_constructor`
|
|
19
|
+
- fixed specs that test backtrace outputs on ruby 3.4
|
|
20
|
+
- Documentation now uses modern (Ruby 3.4) output syntax. (`{foo: 1}` is now printed as is, instead of `{:foo => 1}`
|
|
21
|
+
|
|
3
22
|
## 0.8.0
|
|
4
23
|
|
|
5
24
|
- Add mutation testing (currently about 80% covered)
|
|
@@ -7,11 +26,13 @@
|
|
|
7
26
|
When using the default result implementation, nothing changes for you.
|
|
8
27
|
When you manually pass anything else into it, `succesful?` will return this value. The `failure` and `success` methods
|
|
9
28
|
work on the "Truthy" value of `successful`
|
|
29
|
+
|
|
10
30
|
```ruby
|
|
11
31
|
result = Result.new(some_value, 42)
|
|
12
32
|
result.successful?
|
|
13
33
|
# => 42
|
|
14
34
|
```
|
|
35
|
+
|
|
15
36
|
- Change: `freeze`ing an `Operation` or `Chain` will also freeze their internal config (input, output, steps, etc.)
|
|
16
37
|
|
|
17
38
|
Internal:
|
|
@@ -25,20 +46,20 @@ Internal:
|
|
|
25
46
|
- Breaking: `Teckel::Chain` will not be required by default. require manually if needed `require "teckel/chain"` [GH-24]
|
|
26
47
|
- Breaking: Internally, `Teckel::Operation::Runner` instead of `:success` and `:failure` now only uses `:halt` as it's throw-catch symbol. [GH-26]
|
|
27
48
|
- Add: Using the default `Teckel::Operation::Runner`, `input_constructor` and `result_constructor` will be executed
|
|
28
|
-
within the context of the operation instance. This allows for `input_constructor` to call `fail!` and `success!`
|
|
49
|
+
within the context of the operation instance. This allows for `input_constructor` to call `fail!` and `success!`
|
|
29
50
|
without ever `call`ing the operation. [GH-26]
|
|
30
51
|
|
|
31
|
-
|
|
32
52
|
## 0.6.0
|
|
33
53
|
|
|
34
54
|
- Breaking: Operations return values will be ignored. [GH-21]
|
|
35
|
-
|
|
36
|
-
|
|
55
|
+
- You'll need to use `success!` or `failure!`
|
|
56
|
+
- `success!` and `failure!` are now implemented on the `Runner`, which makes it easier to change their behavior (including the one above).
|
|
37
57
|
|
|
38
58
|
## 0.5.0
|
|
39
59
|
|
|
40
60
|
- Fix: calling chain with settings and no input [GH-14]
|
|
41
61
|
- Add: Default settings for Operation and Chains [GH-17], [GH-18]
|
|
62
|
+
|
|
42
63
|
```ruby
|
|
43
64
|
class MyOperation
|
|
44
65
|
include Teckel::Operation
|
|
@@ -68,6 +89,7 @@ Internal:
|
|
|
68
89
|
```
|
|
69
90
|
|
|
70
91
|
Internal:
|
|
92
|
+
|
|
71
93
|
- Move operation and chain config dsl methods into own module [GH-15]
|
|
72
94
|
- Code simplifications [GH-16]
|
|
73
95
|
|
|
@@ -77,6 +99,7 @@ Internal:
|
|
|
77
99
|
- `#finalize!` no longer freezes the entire Operation or Chain class, only it's settings. [GH-13]
|
|
78
100
|
- Add simple support for using Base classes. [GH-10]
|
|
79
101
|
Removes global configuration `Teckel::Config.default_constructor`
|
|
102
|
+
|
|
80
103
|
```ruby
|
|
81
104
|
class ApplicationOperation
|
|
82
105
|
include Teckel::Operation
|
|
@@ -94,17 +117,21 @@ Internal:
|
|
|
94
117
|
# you cannot call `finalize!` on partially declared Operations
|
|
95
118
|
end
|
|
96
119
|
```
|
|
120
|
+
|
|
97
121
|
- Add support for setting your own Result objects. [GH-9]
|
|
98
122
|
- They should include and implement `Teckel::Result` which is needed by `Chain`.
|
|
99
123
|
- `Chain::StepFailure` got replaced with `Chain::Result`.
|
|
100
124
|
- the `Teckel::Operation::Results` module was removed. To let Operation use the default Result object, use the new helper `result!` instead.
|
|
101
125
|
- Add "settings"/dependency injection to Operation and Chains. [GH-7]
|
|
126
|
+
|
|
102
127
|
```ruby
|
|
103
128
|
MyOperation.with(logger: STDOUT).call(params)
|
|
104
129
|
|
|
105
130
|
MyChain.with(some_step: { logger: STDOUT }).call(params)
|
|
106
131
|
```
|
|
132
|
+
|
|
107
133
|
- [GH-5] Add support for ruby 2.7 pattern matching on Operation and Chain results. Both, array and hash notations are supported:
|
|
134
|
+
|
|
108
135
|
```ruby
|
|
109
136
|
case MyOperation.call(params)
|
|
110
137
|
in [false, value]
|
|
@@ -122,19 +149,20 @@ Internal:
|
|
|
122
149
|
# handle success
|
|
123
150
|
end
|
|
124
151
|
```
|
|
152
|
+
|
|
125
153
|
- Fix setting a config twice to raise an error
|
|
126
154
|
|
|
127
155
|
## 0.3.0
|
|
128
156
|
|
|
129
157
|
- `finalize!`'ing a Chain will also finalize all it's Operations
|
|
130
158
|
- Changed attribute naming of `StepFailure`:
|
|
131
|
-
|
|
132
|
-
|
|
159
|
+
- `.operation` will now give the operation class of the step - was `.step` before
|
|
160
|
+
- `.step` will now give the name of the step (which Operation failed) - was `.step_name` before
|
|
133
161
|
|
|
134
162
|
## 0.2.0
|
|
135
163
|
|
|
136
164
|
- Around Hooks for Chains
|
|
137
|
-
- `finalize!`
|
|
165
|
+
- `finalize!`
|
|
138
166
|
- freezing Chains and Operations, to prevent further changes
|
|
139
167
|
- Operations check their config and raise if any is missing
|
|
140
168
|
|
data/README.md
CHANGED
|
@@ -4,8 +4,7 @@ Ruby service classes with enforced<sup name="footnote-1-source">[1](#footnote-1)
|
|
|
4
4
|
|
|
5
5
|
[][gem]
|
|
6
6
|
[][ci]
|
|
7
|
-
[](https://codeclimate.com/github/fnordfish/teckel/test_coverage)
|
|
7
|
+
[](https://codecov.io/github/fnordfish/teckel)
|
|
9
8
|
[][inch]
|
|
10
9
|
|
|
11
10
|
## Installation
|
data/lib/teckel/chain/config.rb
CHANGED
|
@@ -17,7 +17,7 @@ module Teckel
|
|
|
17
17
|
#
|
|
18
18
|
# @return [<Step>]
|
|
19
19
|
def steps
|
|
20
|
-
@config.
|
|
20
|
+
@config.get_or_set(:steps) { [] }
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
# Set or get the optional around hook.
|
|
@@ -26,9 +26,9 @@ module Teckel
|
|
|
26
26
|
# chain ({Runner}) and the second argument the +input+ data. The hook also
|
|
27
27
|
# needs to return the result.
|
|
28
28
|
#
|
|
29
|
-
# @param callable [Proc
|
|
29
|
+
# @param callable [Proc,#call] The hook to pass chain execution control to. (nil)
|
|
30
30
|
#
|
|
31
|
-
# @return [Proc
|
|
31
|
+
# @return [Proc,#call] The configured hook
|
|
32
32
|
#
|
|
33
33
|
# @example Around hook with block
|
|
34
34
|
# OUTPUTS = []
|
|
@@ -62,7 +62,7 @@ module Teckel
|
|
|
62
62
|
# OUTPUTS #=> ["before start", "after start"]
|
|
63
63
|
# result.success #=> { some: "test" }
|
|
64
64
|
def around(callable = nil, &block)
|
|
65
|
-
@config.
|
|
65
|
+
@config.get_or_set(:around, callable || block)
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
# @!attribute [r] runner()
|
|
@@ -73,7 +73,7 @@ module Teckel
|
|
|
73
73
|
# @param klass [Class] A class like the {Runner}
|
|
74
74
|
# @!visibility protected
|
|
75
75
|
def runner(klass = nil)
|
|
76
|
-
@config.
|
|
76
|
+
@config.get_or_set(:runner, klass) { Runner }
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
# @overload result()
|
|
@@ -85,7 +85,7 @@ module Teckel
|
|
|
85
85
|
# @param klass [Class] The +result+ class
|
|
86
86
|
# @return [Class] The +result+ class configured
|
|
87
87
|
def result(klass = nil)
|
|
88
|
-
@config.
|
|
88
|
+
@config.get_or_set(:result, klass) { const_defined?(:Result, false) ? self::Result : Teckel::Chain::Result }
|
|
89
89
|
end
|
|
90
90
|
|
|
91
91
|
# @overload result_constructor()
|
|
@@ -143,7 +143,7 @@ module Teckel
|
|
|
143
143
|
def result_constructor(sym_or_proc = nil)
|
|
144
144
|
constructor = build_constructor(result, sym_or_proc) unless sym_or_proc.nil?
|
|
145
145
|
|
|
146
|
-
@config.
|
|
146
|
+
@config.get_or_set(:result_constructor, constructor) {
|
|
147
147
|
build_constructor(result, Teckel::DEFAULT_CONSTRUCTOR)
|
|
148
148
|
} || raise(MissingConfigError, "Missing result_constructor config for #{self}")
|
|
149
149
|
end
|
|
@@ -153,7 +153,7 @@ module Teckel
|
|
|
153
153
|
#
|
|
154
154
|
# Explicit call-time settings will *not* get merged with declared default setting.
|
|
155
155
|
#
|
|
156
|
-
# @param settings [Hash{String,Symbol => Object}] Set settings for a step by it's name
|
|
156
|
+
# @param settings [Hash{(String,Symbol) => Object}] Set settings for a step by it's name
|
|
157
157
|
#
|
|
158
158
|
# @example
|
|
159
159
|
# class MyOperation
|
|
@@ -188,15 +188,18 @@ module Teckel
|
|
|
188
188
|
# result = Chain.with(a: { other: "What" }).call
|
|
189
189
|
# result.success #=> {say: nil, other: "What"}
|
|
190
190
|
def default_settings!(settings) # :nodoc: The bang is for consistency with the Operation class
|
|
191
|
-
@config.
|
|
191
|
+
@config.get_or_set(:default_settings, settings)
|
|
192
192
|
end
|
|
193
193
|
|
|
194
194
|
# Getter for configured default settings
|
|
195
|
-
# @return [
|
|
195
|
+
# @return [NilClass]
|
|
196
|
+
# @return [#call] The callable constructor
|
|
196
197
|
def default_settings
|
|
197
|
-
@config.
|
|
198
|
+
@config.get_or_set(:default_settings)
|
|
198
199
|
end
|
|
199
200
|
|
|
201
|
+
# @!visibility private
|
|
202
|
+
# @return [Array<Symbol>]
|
|
200
203
|
REQUIRED_CONFIGS = %i[around runner result result_constructor].freeze
|
|
201
204
|
|
|
202
205
|
# @!visibility private
|
|
@@ -227,7 +230,7 @@ module Teckel
|
|
|
227
230
|
# @return [self]
|
|
228
231
|
# @!visibility public
|
|
229
232
|
def dup
|
|
230
|
-
dup_config(super())
|
|
233
|
+
dup_config(super()) # standard:disable Style/SuperArguments
|
|
231
234
|
end
|
|
232
235
|
|
|
233
236
|
# Produces a clone of this chain.
|
|
@@ -237,9 +240,9 @@ module Teckel
|
|
|
237
240
|
# @!visibility public
|
|
238
241
|
def clone
|
|
239
242
|
if frozen?
|
|
240
|
-
super()
|
|
243
|
+
super() # standard:disable Style/SuperArguments
|
|
241
244
|
else
|
|
242
|
-
dup_config(super())
|
|
245
|
+
dup_config(super()) # standard:disable Style/SuperArguments
|
|
243
246
|
end
|
|
244
247
|
end
|
|
245
248
|
|
|
@@ -250,7 +253,7 @@ module Teckel
|
|
|
250
253
|
def freeze
|
|
251
254
|
steps.freeze
|
|
252
255
|
@config.freeze
|
|
253
|
-
super()
|
|
256
|
+
super() # standard:disable Style/SuperArguments
|
|
254
257
|
end
|
|
255
258
|
|
|
256
259
|
# @!visibility private
|
|
@@ -263,9 +266,7 @@ module Teckel
|
|
|
263
266
|
base.instance_variable_set(:@config, Teckel::Config.new)
|
|
264
267
|
end
|
|
265
268
|
|
|
266
|
-
private
|
|
267
|
-
|
|
268
|
-
def dup_config(other_class)
|
|
269
|
+
private def dup_config(other_class)
|
|
269
270
|
new_config = @config.dup
|
|
270
271
|
new_config.replace(:steps) { steps.dup }
|
|
271
272
|
|
|
@@ -273,7 +274,7 @@ module Teckel
|
|
|
273
274
|
other_class
|
|
274
275
|
end
|
|
275
276
|
|
|
276
|
-
def build_constructor(on, sym_or_proc)
|
|
277
|
+
private def build_constructor(on, sym_or_proc)
|
|
277
278
|
case sym_or_proc
|
|
278
279
|
when Proc
|
|
279
280
|
sym_or_proc
|
data/lib/teckel/chain/result.rb
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'forwardable'
|
|
4
|
-
|
|
5
3
|
module Teckel
|
|
6
4
|
module Chain
|
|
7
5
|
class Result < Teckel::Operation::Result
|
|
8
|
-
extend Forwardable
|
|
9
|
-
|
|
10
6
|
# @param value [Object] The result value
|
|
11
7
|
# @param success [Boolean] whether this is a successful result
|
|
12
8
|
# @param step [Teckel::Chain::Step]
|
|
@@ -16,13 +12,13 @@ module Teckel
|
|
|
16
12
|
end
|
|
17
13
|
|
|
18
14
|
class << self
|
|
19
|
-
|
|
15
|
+
alias_method :[], :new
|
|
20
16
|
end
|
|
21
17
|
|
|
22
|
-
#
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
18
|
+
# @return [String,Symbol] The step name of the failed operation.
|
|
19
|
+
def step
|
|
20
|
+
@step.name
|
|
21
|
+
end
|
|
26
22
|
|
|
27
23
|
def deconstruct
|
|
28
24
|
[successful?, @step.name, value]
|
data/lib/teckel/chain/runner.rb
CHANGED
|
@@ -7,9 +7,13 @@ module Teckel
|
|
|
7
7
|
# @!visibility protected
|
|
8
8
|
class Runner
|
|
9
9
|
# @!visibility private
|
|
10
|
-
|
|
10
|
+
# @return [Object]
|
|
11
|
+
UNDEFINED = Teckel::UNDEFINED
|
|
11
12
|
|
|
12
13
|
# @!visibility private
|
|
14
|
+
# @attr [Object] value the return value / result of the step execution
|
|
15
|
+
# @attr [Boolean] success whether the step has been executed successfully
|
|
16
|
+
# @attr [Teckel::Chain::Step] the step instance
|
|
13
17
|
StepResult = Struct.new(:value, :success, :step)
|
|
14
18
|
|
|
15
19
|
def initialize(chain, settings = UNDEFINED)
|
|
@@ -32,9 +36,7 @@ module Teckel
|
|
|
32
36
|
settings.eql?(UNDEFINED) ? chain.steps : steps_with_settings
|
|
33
37
|
end
|
|
34
38
|
|
|
35
|
-
private
|
|
36
|
-
|
|
37
|
-
def run(input)
|
|
39
|
+
private def run(input)
|
|
38
40
|
steps.each_with_object(StepResult.new(input)) do |step, step_result|
|
|
39
41
|
result = step.operation.call(step_result.value)
|
|
40
42
|
|
|
@@ -46,11 +48,11 @@ module Teckel
|
|
|
46
48
|
end
|
|
47
49
|
end
|
|
48
50
|
|
|
49
|
-
def step_with_settings(step)
|
|
51
|
+
private def step_with_settings(step)
|
|
50
52
|
settings.key?(step.name) ? step.with(settings[step.name]) : step
|
|
51
53
|
end
|
|
52
54
|
|
|
53
|
-
def steps_with_settings
|
|
55
|
+
private def steps_with_settings
|
|
54
56
|
Enumerator.new do |yielder|
|
|
55
57
|
chain.steps.each do |step|
|
|
56
58
|
yielder << step_with_settings(step)
|
data/lib/teckel/chain.rb
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
4
|
-
require_relative
|
|
5
|
-
require_relative
|
|
6
|
-
require_relative
|
|
3
|
+
require_relative "chain/config"
|
|
4
|
+
require_relative "chain/step"
|
|
5
|
+
require_relative "chain/result"
|
|
6
|
+
require_relative "chain/runner"
|
|
7
7
|
|
|
8
8
|
module Teckel
|
|
9
9
|
# Railway style execution of multiple Operations.
|
|
@@ -32,10 +32,7 @@ module Teckel
|
|
|
32
32
|
# List of all possible errors
|
|
33
33
|
# @return [<Class>] List of all steps {Teckel::Operation.error}s
|
|
34
34
|
def errors
|
|
35
|
-
steps.
|
|
36
|
-
err = step.operation.error
|
|
37
|
-
m << err if err
|
|
38
|
-
end
|
|
35
|
+
steps.map { |step| step.operation.error }
|
|
39
36
|
end
|
|
40
37
|
|
|
41
38
|
# The primary interface to call the chain with the given input.
|
|
@@ -45,13 +42,13 @@ module Teckel
|
|
|
45
42
|
# @return [Teckel::Chain::Result] The result object wrapping
|
|
46
43
|
# the result value, the success state and last executed step.
|
|
47
44
|
def call(input = nil)
|
|
48
|
-
default_settings =
|
|
45
|
+
default_settings = default_settings()
|
|
49
46
|
|
|
50
47
|
runner =
|
|
51
48
|
if default_settings
|
|
52
|
-
|
|
49
|
+
runner().new(self, default_settings)
|
|
53
50
|
else
|
|
54
|
-
|
|
51
|
+
runner().new(self)
|
|
55
52
|
end
|
|
56
53
|
|
|
57
54
|
if around
|
|
@@ -61,16 +58,20 @@ module Teckel
|
|
|
61
58
|
end
|
|
62
59
|
end
|
|
63
60
|
|
|
64
|
-
#
|
|
61
|
+
# Provide settings to the configured steps.
|
|
62
|
+
#
|
|
63
|
+
# @param settings [Hash{(String,Symbol) => Object}] Set settings for a step by it's name
|
|
64
|
+
# @return [#call] A callable, either a {Teckel::Chain::Runner} or,
|
|
65
|
+
# when configured with an around hook, a +Proc+
|
|
65
66
|
def with(settings)
|
|
66
|
-
runner =
|
|
67
|
+
runner = runner().new(self, settings)
|
|
67
68
|
if around
|
|
68
|
-
|
|
69
|
+
around.curry[runner]
|
|
69
70
|
else
|
|
70
71
|
runner
|
|
71
72
|
end
|
|
72
73
|
end
|
|
73
|
-
|
|
74
|
+
alias_method :set, :with
|
|
74
75
|
end
|
|
75
76
|
|
|
76
77
|
def self.included(receiver)
|
data/lib/teckel/config.rb
CHANGED
|
@@ -15,11 +15,16 @@ module Teckel
|
|
|
15
15
|
# - sets (and returns) the blocks return value otherwise
|
|
16
16
|
# - calling without +value+ and +block+ works like {Hash#[]}
|
|
17
17
|
#
|
|
18
|
+
# @param key [Symbol,String] Name of the configuration
|
|
19
|
+
# @param value [Object] Value of the configuration
|
|
20
|
+
# @yield [key] If using in fetch mode and no value has been set
|
|
21
|
+
# @yieldparam key [Symbol,String] Name of the configuration
|
|
22
|
+
# @return [Object]
|
|
18
23
|
# @raise [FrozenConfigError] When overwriting a key
|
|
19
24
|
# @!visibility private
|
|
20
|
-
def
|
|
25
|
+
def get_or_set(key, value = nil, &block)
|
|
21
26
|
if value.nil?
|
|
22
|
-
|
|
27
|
+
_get_or_set(key, &block)
|
|
23
28
|
elsif @config.key?(key)
|
|
24
29
|
raise FrozenConfigError, "Configuration #{key} is already set"
|
|
25
30
|
else
|
|
@@ -28,6 +33,9 @@ module Teckel
|
|
|
28
33
|
end
|
|
29
34
|
|
|
30
35
|
# @!visibility private
|
|
36
|
+
# @param key [Symbol,String] Name of the configuration
|
|
37
|
+
# @yieldreturn [Object] The new setting
|
|
38
|
+
# @return [Object,nil] The new setting or +nil+ if not replaced
|
|
31
39
|
def replace(key)
|
|
32
40
|
@config[key] = yield if @config.key?(key)
|
|
33
41
|
end
|
|
@@ -35,19 +43,17 @@ module Teckel
|
|
|
35
43
|
# @!visibility private
|
|
36
44
|
def freeze
|
|
37
45
|
@config.freeze
|
|
38
|
-
super()
|
|
46
|
+
super() # standard:disable Style/SuperArguments
|
|
39
47
|
end
|
|
40
48
|
|
|
41
49
|
# @!visibility private
|
|
42
50
|
def dup
|
|
43
|
-
super()
|
|
44
|
-
|
|
45
|
-
|
|
51
|
+
copy = super() # standard:disable Style/SuperArguments
|
|
52
|
+
copy.instance_variable_set(:@config, @config.dup)
|
|
53
|
+
copy
|
|
46
54
|
end
|
|
47
55
|
|
|
48
|
-
private
|
|
49
|
-
|
|
50
|
-
def get_or_set(key, &block)
|
|
56
|
+
private def _get_or_set(key, &block)
|
|
51
57
|
if block
|
|
52
58
|
@config[key] ||= @config.fetch(key, &block)
|
|
53
59
|
else
|
data/lib/teckel/contracts.rb
CHANGED
|
@@ -5,14 +5,14 @@ module Teckel
|
|
|
5
5
|
# Simple contract for enforcing data to be not set or +nil+
|
|
6
6
|
module None
|
|
7
7
|
class << self
|
|
8
|
-
# Always return nil
|
|
9
|
-
# @return
|
|
8
|
+
# Always return +nil+
|
|
9
|
+
# @return [NilClass]
|
|
10
10
|
# @raise [ArgumentError] when called with any non-nil arguments
|
|
11
11
|
def [](*args)
|
|
12
12
|
raise ArgumentError, "None called with arguments" if args.any?(&:itself)
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
alias_method :new, :[]
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
18
|
end
|