teckel 0.7.0 → 0.9.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 +48 -7
- data/README.md +3 -3
- data/lib/teckel/chain/config.rb +35 -23
- data/lib/teckel/chain/result.rb +5 -9
- data/lib/teckel/chain/runner.rb +9 -7
- data/lib/teckel/chain.rb +19 -13
- data/lib/teckel/config.rb +15 -9
- data/lib/teckel/contracts.rb +3 -3
- data/lib/teckel/operation/config.rb +55 -48
- data/lib/teckel/operation/result.rb +16 -16
- data/lib/teckel/operation/runner.rb +5 -5
- data/lib/teckel/operation.rb +37 -18
- data/lib/teckel/result.rb +5 -3
- data/lib/teckel/version.rb +2 -1
- data/lib/teckel.rb +4 -1
- metadata +34 -53
- 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 -180
- data/spec/config_spec.rb +0 -26
- data/spec/doctest_helper.rb +0 -8
- data/spec/operation/contract_trace_spec.rb +0 -116
- data/spec/operation/default_settings_spec.rb +0 -94
- 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 -55
- data/spec/operation/results_spec.rb +0 -117
- data/spec/operation_spec.rb +0 -483
- data/spec/rb27/pattern_matching_spec.rb +0 -193
- data/spec/result_spec.rb +0 -22
- data/spec/spec_helper.rb +0 -28
- 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: c8dc1958f2645a6c57178a595b7d4364c9b2613e3c5adc532e0c8fd0cc8c2c22
|
4
|
+
data.tar.gz: cc0ef87983b17af9c16df5f4cc77a826a445fb7dc1f38db4de6cef7eef3b27c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b9e5dde43b07ec1ae8fb6a1964990cdbdac430bd2c3ba4e73fd137fbeac3f1e4a3faf10e05098da00414a8ed17b6b8ce4316593ea1160bf976aeb2bc550ab6d
|
7
|
+
data.tar.gz: 5fd5bd9a76fcf3ad4794de79e94eaba128dc6cbcac1a12e92eafa0aef36d5b18496d8d509738706f23fe555e6d482c21e20cd0384c756e4b02952d4ce52bf770
|
data/CHANGELOG.md
CHANGED
@@ -1,24 +1,58 @@
|
|
1
1
|
# Changes
|
2
2
|
|
3
|
+
## 0.9.0
|
4
|
+
|
5
|
+
- Internal housekeeping
|
6
|
+
- Add ruby 3.4 and 'head' to CI
|
7
|
+
- Ruby < 3 won't run mutation test
|
8
|
+
- moved to standard.rb for linting and formatting
|
9
|
+
- removed usage of `forwardable` in favor of explicit delegation methods
|
10
|
+
- renamed internal `Teckel::Config.for` to `get_or_set`
|
11
|
+
- renamed internal `Teckel::Operation::Config.get_set_constructor` to `get_or_set_constructor`
|
12
|
+
- fixed specs that test backtrace outputs on ruby 3.4
|
13
|
+
- Documentation now uses modern (Ruby 3.4) output syntax. (`{foo: 1}` is now printed as is, instead of `{:foo => 1}`
|
14
|
+
|
15
|
+
## 0.8.0
|
16
|
+
|
17
|
+
- Add mutation testing (currently about 80% covered)
|
18
|
+
- Breaking: `Teckel::Operation::Result` no longer converts the `successful` value to a boolean.
|
19
|
+
When using the default result implementation, nothing changes for you.
|
20
|
+
When you manually pass anything else into it, `succesful?` will return this value. The `failure` and `success` methods
|
21
|
+
work on the "Truthy" value of `successful`
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
result = Result.new(some_value, 42)
|
25
|
+
result.successful?
|
26
|
+
# => 42
|
27
|
+
```
|
28
|
+
|
29
|
+
- Change: `freeze`ing an `Operation` or `Chain` will also freeze their internal config (input, output, steps, etc.)
|
30
|
+
|
31
|
+
Internal:
|
32
|
+
|
33
|
+
- Some refactoring to cover mutations
|
34
|
+
- Extracted creating the runable `Operation` instance into a new, public `runable(settings = UNDEFINED)` method.
|
35
|
+
Mainly to reduce code duplication but this also makes testing, stubbing and mocking easier.
|
36
|
+
|
3
37
|
## 0.7.0
|
4
38
|
|
5
39
|
- Breaking: `Teckel::Chain` will not be required by default. require manually if needed `require "teckel/chain"` [GH-24]
|
6
40
|
- Breaking: Internally, `Teckel::Operation::Runner` instead of `:success` and `:failure` now only uses `:halt` as it's throw-catch symbol. [GH-26]
|
7
41
|
- Add: Using the default `Teckel::Operation::Runner`, `input_constructor` and `result_constructor` will be executed
|
8
|
-
within the context of the operation instance. This allows for `input_constructor` to call `fail!` and `success!`
|
42
|
+
within the context of the operation instance. This allows for `input_constructor` to call `fail!` and `success!`
|
9
43
|
without ever `call`ing the operation. [GH-26]
|
10
44
|
|
11
|
-
|
12
45
|
## 0.6.0
|
13
46
|
|
14
47
|
- Breaking: Operations return values will be ignored. [GH-21]
|
15
|
-
|
16
|
-
|
48
|
+
- You'll need to use `success!` or `failure!`
|
49
|
+
- `success!` and `failure!` are now implemented on the `Runner`, which makes it easier to change their behavior (including the one above).
|
17
50
|
|
18
51
|
## 0.5.0
|
19
52
|
|
20
53
|
- Fix: calling chain with settings and no input [GH-14]
|
21
54
|
- Add: Default settings for Operation and Chains [GH-17], [GH-18]
|
55
|
+
|
22
56
|
```ruby
|
23
57
|
class MyOperation
|
24
58
|
include Teckel::Operation
|
@@ -48,6 +82,7 @@
|
|
48
82
|
```
|
49
83
|
|
50
84
|
Internal:
|
85
|
+
|
51
86
|
- Move operation and chain config dsl methods into own module [GH-15]
|
52
87
|
- Code simplifications [GH-16]
|
53
88
|
|
@@ -57,6 +92,7 @@ Internal:
|
|
57
92
|
- `#finalize!` no longer freezes the entire Operation or Chain class, only it's settings. [GH-13]
|
58
93
|
- Add simple support for using Base classes. [GH-10]
|
59
94
|
Removes global configuration `Teckel::Config.default_constructor`
|
95
|
+
|
60
96
|
```ruby
|
61
97
|
class ApplicationOperation
|
62
98
|
include Teckel::Operation
|
@@ -74,17 +110,21 @@ Internal:
|
|
74
110
|
# you cannot call `finalize!` on partially declared Operations
|
75
111
|
end
|
76
112
|
```
|
113
|
+
|
77
114
|
- Add support for setting your own Result objects. [GH-9]
|
78
115
|
- They should include and implement `Teckel::Result` which is needed by `Chain`.
|
79
116
|
- `Chain::StepFailure` got replaced with `Chain::Result`.
|
80
117
|
- the `Teckel::Operation::Results` module was removed. To let Operation use the default Result object, use the new helper `result!` instead.
|
81
118
|
- Add "settings"/dependency injection to Operation and Chains. [GH-7]
|
119
|
+
|
82
120
|
```ruby
|
83
121
|
MyOperation.with(logger: STDOUT).call(params)
|
84
122
|
|
85
123
|
MyChain.with(some_step: { logger: STDOUT }).call(params)
|
86
124
|
```
|
125
|
+
|
87
126
|
- [GH-5] Add support for ruby 2.7 pattern matching on Operation and Chain results. Both, array and hash notations are supported:
|
127
|
+
|
88
128
|
```ruby
|
89
129
|
case MyOperation.call(params)
|
90
130
|
in [false, value]
|
@@ -102,19 +142,20 @@ Internal:
|
|
102
142
|
# handle success
|
103
143
|
end
|
104
144
|
```
|
145
|
+
|
105
146
|
- Fix setting a config twice to raise an error
|
106
147
|
|
107
148
|
## 0.3.0
|
108
149
|
|
109
150
|
- `finalize!`'ing a Chain will also finalize all it's Operations
|
110
151
|
- Changed attribute naming of `StepFailure`:
|
111
|
-
|
112
|
-
|
152
|
+
- `.operation` will now give the operation class of the step - was `.step` before
|
153
|
+
- `.step` will now give the name of the step (which Operation failed) - was `.step_name` before
|
113
154
|
|
114
155
|
## 0.2.0
|
115
156
|
|
116
157
|
- Around Hooks for Chains
|
117
|
-
- `finalize!`
|
158
|
+
- `finalize!`
|
118
159
|
- freezing Chains and Operations, to prevent further changes
|
119
160
|
- Operations check their config and raise if any is missing
|
120
161
|
|
data/README.md
CHANGED
@@ -3,10 +3,10 @@
|
|
3
3
|
Ruby service classes with enforced<sup name="footnote-1-source">[1](#footnote-1)</sup> input, output and error data structure definition.
|
4
4
|
|
5
5
|
[][gem]
|
6
|
-
[][ci]
|
7
7
|
[](https://codeclimate.com/github/fnordfish/teckel/maintainability)
|
8
8
|
[](https://codeclimate.com/github/fnordfish/teckel/test_coverage)
|
9
|
-
[][inch]
|
10
10
|
|
11
11
|
## Installation
|
12
12
|
|
@@ -95,5 +95,5 @@ Please also see [DEVELOPMENT.md](DEVELOPMENT.md) for planned features and genera
|
|
95
95
|
- <a name="footnote-1">1</a>: Obviously, it's still Ruby and you can cheat. Don’t! [↩](#footnote-1-source)
|
96
96
|
|
97
97
|
[gem]: https://rubygems.org/gems/teckel
|
98
|
-
[ci]: https://github.com/fnordfish/teckel/actions
|
98
|
+
[ci]: https://github.com/fnordfish/teckel/actions/workflows/specs.yml
|
99
99
|
[inch]: http://inch-ci.org/github/fnordfish/teckel
|
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,17 +143,17 @@ 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
|
150
150
|
|
151
|
-
# Declare default settings operation
|
151
|
+
# Declare default settings operation in this chain should use when called without
|
152
152
|
# {Teckel::Chain::ClassMethods#with #with}.
|
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,15 +240,25 @@ 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
|
|
249
|
+
# Prevents further modifications to this chain and its config
|
250
|
+
#
|
251
|
+
# @return [self]
|
252
|
+
# @!visibility public
|
253
|
+
def freeze
|
254
|
+
steps.freeze
|
255
|
+
@config.freeze
|
256
|
+
super() # standard:disable Style/SuperArguments
|
257
|
+
end
|
258
|
+
|
246
259
|
# @!visibility private
|
247
260
|
def inherited(subclass)
|
248
|
-
super
|
261
|
+
super(dup_config(subclass))
|
249
262
|
end
|
250
263
|
|
251
264
|
# @!visibility private
|
@@ -253,9 +266,7 @@ module Teckel
|
|
253
266
|
base.instance_variable_set(:@config, Teckel::Config.new)
|
254
267
|
end
|
255
268
|
|
256
|
-
private
|
257
|
-
|
258
|
-
def dup_config(other_class)
|
269
|
+
private def dup_config(other_class)
|
259
270
|
new_config = @config.dup
|
260
271
|
new_config.replace(:steps) { steps.dup }
|
261
272
|
|
@@ -263,11 +274,12 @@ module Teckel
|
|
263
274
|
other_class
|
264
275
|
end
|
265
276
|
|
266
|
-
def build_constructor(on, sym_or_proc)
|
267
|
-
|
268
|
-
|
269
|
-
elsif sym_or_proc.respond_to?(:call)
|
277
|
+
private def build_constructor(on, sym_or_proc)
|
278
|
+
case sym_or_proc
|
279
|
+
when Proc
|
270
280
|
sym_or_proc
|
281
|
+
when Symbol
|
282
|
+
on.public_method(sym_or_proc) if on.respond_to?(sym_or_proc)
|
271
283
|
end
|
272
284
|
end
|
273
285
|
end
|
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)
|
@@ -29,12 +33,10 @@ module Teckel
|
|
29
33
|
end
|
30
34
|
|
31
35
|
def steps
|
32
|
-
settings
|
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.
|
@@ -45,13 +45,13 @@ module Teckel
|
|
45
45
|
# @return [Teckel::Chain::Result] The result object wrapping
|
46
46
|
# the result value, the success state and last executed step.
|
47
47
|
def call(input = nil)
|
48
|
-
default_settings =
|
48
|
+
default_settings = default_settings()
|
49
49
|
|
50
50
|
runner =
|
51
51
|
if default_settings
|
52
|
-
|
52
|
+
runner().new(self, default_settings)
|
53
53
|
else
|
54
|
-
|
54
|
+
runner().new(self)
|
55
55
|
end
|
56
56
|
|
57
57
|
if around
|
@@ -61,21 +61,27 @@ module Teckel
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
-
#
|
64
|
+
# Provide settings to the configured steps.
|
65
|
+
#
|
66
|
+
# @param settings [Hash{(String,Symbol) => Object}] Set settings for a step by it's name
|
67
|
+
# @return [#call] A callable, either a {Teckel::Chain::Runner} or,
|
68
|
+
# when configured with an around hook, a +Proc+
|
65
69
|
def with(settings)
|
66
|
-
runner =
|
70
|
+
runner = runner().new(self, settings)
|
67
71
|
if around
|
68
|
-
|
72
|
+
around.curry[runner]
|
69
73
|
else
|
70
74
|
runner
|
71
75
|
end
|
72
76
|
end
|
73
|
-
|
77
|
+
alias_method :set, :with
|
74
78
|
end
|
75
79
|
|
76
80
|
def self.included(receiver)
|
77
|
-
receiver.
|
78
|
-
|
81
|
+
receiver.class_eval do
|
82
|
+
extend Config
|
83
|
+
extend ClassMethods
|
84
|
+
end
|
79
85
|
end
|
80
86
|
end
|
81
87
|
end
|
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
|