teckel 0.8.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 +28 -7
- 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 +15 -11
- 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 +8 -8
- data/lib/teckel/operation/runner.rb +1 -1
- data/lib/teckel/operation.rb +5 -5
- data/lib/teckel/result.rb +2 -2
- data/lib/teckel/version.rb +2 -1
- data/lib/teckel.rb +4 -1
- metadata +19 -54
- 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: 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,5 +1,17 @@
|
|
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
|
+
|
3
15
|
## 0.8.0
|
4
16
|
|
5
17
|
- Add mutation testing (currently about 80% covered)
|
@@ -7,11 +19,13 @@
|
|
7
19
|
When using the default result implementation, nothing changes for you.
|
8
20
|
When you manually pass anything else into it, `succesful?` will return this value. The `failure` and `success` methods
|
9
21
|
work on the "Truthy" value of `successful`
|
22
|
+
|
10
23
|
```ruby
|
11
24
|
result = Result.new(some_value, 42)
|
12
25
|
result.successful?
|
13
26
|
# => 42
|
14
27
|
```
|
28
|
+
|
15
29
|
- Change: `freeze`ing an `Operation` or `Chain` will also freeze their internal config (input, output, steps, etc.)
|
16
30
|
|
17
31
|
Internal:
|
@@ -25,20 +39,20 @@ Internal:
|
|
25
39
|
- Breaking: `Teckel::Chain` will not be required by default. require manually if needed `require "teckel/chain"` [GH-24]
|
26
40
|
- Breaking: Internally, `Teckel::Operation::Runner` instead of `:success` and `:failure` now only uses `:halt` as it's throw-catch symbol. [GH-26]
|
27
41
|
- 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!`
|
42
|
+
within the context of the operation instance. This allows for `input_constructor` to call `fail!` and `success!`
|
29
43
|
without ever `call`ing the operation. [GH-26]
|
30
44
|
|
31
|
-
|
32
45
|
## 0.6.0
|
33
46
|
|
34
47
|
- Breaking: Operations return values will be ignored. [GH-21]
|
35
|
-
|
36
|
-
|
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).
|
37
50
|
|
38
51
|
## 0.5.0
|
39
52
|
|
40
53
|
- Fix: calling chain with settings and no input [GH-14]
|
41
54
|
- Add: Default settings for Operation and Chains [GH-17], [GH-18]
|
55
|
+
|
42
56
|
```ruby
|
43
57
|
class MyOperation
|
44
58
|
include Teckel::Operation
|
@@ -68,6 +82,7 @@ Internal:
|
|
68
82
|
```
|
69
83
|
|
70
84
|
Internal:
|
85
|
+
|
71
86
|
- Move operation and chain config dsl methods into own module [GH-15]
|
72
87
|
- Code simplifications [GH-16]
|
73
88
|
|
@@ -77,6 +92,7 @@ Internal:
|
|
77
92
|
- `#finalize!` no longer freezes the entire Operation or Chain class, only it's settings. [GH-13]
|
78
93
|
- Add simple support for using Base classes. [GH-10]
|
79
94
|
Removes global configuration `Teckel::Config.default_constructor`
|
95
|
+
|
80
96
|
```ruby
|
81
97
|
class ApplicationOperation
|
82
98
|
include Teckel::Operation
|
@@ -94,17 +110,21 @@ Internal:
|
|
94
110
|
# you cannot call `finalize!` on partially declared Operations
|
95
111
|
end
|
96
112
|
```
|
113
|
+
|
97
114
|
- Add support for setting your own Result objects. [GH-9]
|
98
115
|
- They should include and implement `Teckel::Result` which is needed by `Chain`.
|
99
116
|
- `Chain::StepFailure` got replaced with `Chain::Result`.
|
100
117
|
- the `Teckel::Operation::Results` module was removed. To let Operation use the default Result object, use the new helper `result!` instead.
|
101
118
|
- Add "settings"/dependency injection to Operation and Chains. [GH-7]
|
119
|
+
|
102
120
|
```ruby
|
103
121
|
MyOperation.with(logger: STDOUT).call(params)
|
104
122
|
|
105
123
|
MyChain.with(some_step: { logger: STDOUT }).call(params)
|
106
124
|
```
|
125
|
+
|
107
126
|
- [GH-5] Add support for ruby 2.7 pattern matching on Operation and Chain results. Both, array and hash notations are supported:
|
127
|
+
|
108
128
|
```ruby
|
109
129
|
case MyOperation.call(params)
|
110
130
|
in [false, value]
|
@@ -122,19 +142,20 @@ Internal:
|
|
122
142
|
# handle success
|
123
143
|
end
|
124
144
|
```
|
145
|
+
|
125
146
|
- Fix setting a config twice to raise an error
|
126
147
|
|
127
148
|
## 0.3.0
|
128
149
|
|
129
150
|
- `finalize!`'ing a Chain will also finalize all it's Operations
|
130
151
|
- Changed attribute naming of `StepFailure`:
|
131
|
-
|
132
|
-
|
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
|
133
154
|
|
134
155
|
## 0.2.0
|
135
156
|
|
136
157
|
- Around Hooks for Chains
|
137
|
-
- `finalize!`
|
158
|
+
- `finalize!`
|
138
159
|
- freezing Chains and Operations, to prevent further changes
|
139
160
|
- Operations check their config and raise if any is missing
|
140
161
|
|
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.
|
@@ -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,16 +61,20 @@ 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)
|
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
|
@@ -11,7 +11,7 @@ module Teckel
|
|
11
11
|
# @param klass [Class] The +input+ class
|
12
12
|
# @return [Class] The +input+ class
|
13
13
|
def input(klass = nil)
|
14
|
-
@config.
|
14
|
+
@config.get_or_set(:input, klass) { self::Input if const_defined?(:Input) } ||
|
15
15
|
raise(MissingConfigError, "Missing input config for #{self}")
|
16
16
|
end
|
17
17
|
|
@@ -57,7 +57,7 @@ module Teckel
|
|
57
57
|
#
|
58
58
|
# MyOperation.input_constructor.is_a?(Proc) #=> true
|
59
59
|
def input_constructor(sym_or_proc = nil)
|
60
|
-
|
60
|
+
get_or_set_constructor(:input_constructor, input, sym_or_proc)
|
61
61
|
end
|
62
62
|
|
63
63
|
# @overload output()
|
@@ -70,7 +70,7 @@ module Teckel
|
|
70
70
|
# @param klass [Class] The +output+ class
|
71
71
|
# @return [Class] The +output+ class
|
72
72
|
def output(klass = nil)
|
73
|
-
@config.
|
73
|
+
@config.get_or_set(:output, klass) { self::Output if const_defined?(:Output) } ||
|
74
74
|
raise(MissingConfigError, "Missing output config for #{self}")
|
75
75
|
end
|
76
76
|
|
@@ -102,7 +102,7 @@ module Teckel
|
|
102
102
|
# output_constructor ->(name, options) { Output.new(name: name, **options) }
|
103
103
|
# end
|
104
104
|
def output_constructor(sym_or_proc = nil)
|
105
|
-
|
105
|
+
get_or_set_constructor(:output_constructor, output, sym_or_proc)
|
106
106
|
end
|
107
107
|
|
108
108
|
# @overload error()
|
@@ -114,7 +114,7 @@ module Teckel
|
|
114
114
|
# @param klass [Class] The +error+ class
|
115
115
|
# @return [Class,nil] The +error+ class or +nil+ if it does not error
|
116
116
|
def error(klass = nil)
|
117
|
-
@config.
|
117
|
+
@config.get_or_set(:error, klass) { self::Error if const_defined?(:Error) } ||
|
118
118
|
raise(MissingConfigError, "Missing error config for #{self}")
|
119
119
|
end
|
120
120
|
|
@@ -146,7 +146,7 @@ module Teckel
|
|
146
146
|
# error_constructor ->(name, options) { Error.new(name: name, **options) }
|
147
147
|
# end
|
148
148
|
def error_constructor(sym_or_proc = nil)
|
149
|
-
|
149
|
+
get_or_set_constructor(:error_constructor, error, sym_or_proc)
|
150
150
|
end
|
151
151
|
|
152
152
|
# @!endgroup
|
@@ -160,7 +160,7 @@ module Teckel
|
|
160
160
|
# @param klass [Class] The +settings+ class
|
161
161
|
# @return [Class] The +settings+ class configured
|
162
162
|
def settings(klass = nil)
|
163
|
-
@config.
|
163
|
+
@config.get_or_set(:settings, klass) { const_defined?(:Settings) ? self::Settings : none }
|
164
164
|
end
|
165
165
|
|
166
166
|
# @overload settings_constructor()
|
@@ -187,7 +187,7 @@ module Teckel
|
|
187
187
|
# settings_constructor :new
|
188
188
|
# end
|
189
189
|
def settings_constructor(sym_or_proc = nil)
|
190
|
-
|
190
|
+
get_or_set_constructor(:settings_constructor, settings, sym_or_proc) ||
|
191
191
|
raise(MissingConfigError, "Missing settings_constructor config for #{self}")
|
192
192
|
end
|
193
193
|
|
@@ -222,13 +222,14 @@ module Teckel
|
|
222
222
|
|
223
223
|
callable ||= -> { settings_constructor.call(*args) }
|
224
224
|
|
225
|
-
@config.
|
225
|
+
@config.get_or_set(:default_settings, callable)
|
226
226
|
end
|
227
227
|
|
228
228
|
# Getter for configured default settings
|
229
|
-
# @return [
|
229
|
+
# @return [NilClass]
|
230
|
+
# @return [#call] The callable constructor
|
230
231
|
def default_settings
|
231
|
-
@config.
|
232
|
+
@config.get_or_set(:default_settings)
|
232
233
|
end
|
233
234
|
|
234
235
|
# @overload runner()
|
@@ -240,12 +241,12 @@ module Teckel
|
|
240
241
|
# @param klass [Class] A class like the {Runner}
|
241
242
|
# @!visibility protected
|
242
243
|
def runner(klass = nil)
|
243
|
-
@config.
|
244
|
+
@config.get_or_set(:runner, klass) { Runner }
|
244
245
|
end
|
245
246
|
|
246
247
|
# @overload result()
|
247
248
|
# Get the configured result object class wrapping {error} or {output}.
|
248
|
-
# The {ValueResult} default will act as a pass-through
|
249
|
+
# The {ValueResult} default will act as a pass-through. Any error
|
249
250
|
# or output will just returned as-is.
|
250
251
|
# @return [Class] The +result+ class, or {ValueResult} as default
|
251
252
|
#
|
@@ -254,9 +255,12 @@ module Teckel
|
|
254
255
|
# @param klass [Class] The +result+ class
|
255
256
|
# @return [Class] The +result+ class configured
|
256
257
|
def result(klass = nil)
|
257
|
-
@config.
|
258
|
+
@config.get_or_set(:result, klass) { const_defined?(:Result, false) ? self::Result : ValueResult }
|
258
259
|
end
|
259
260
|
|
261
|
+
# @param sym_or_proc [Symbol,Proc,NilClass]
|
262
|
+
# @return [#call]
|
263
|
+
#
|
260
264
|
# @overload result_constructor()
|
261
265
|
# The callable constructor to build an instance of the +result+ class.
|
262
266
|
# Defaults to {Teckel::DEFAULT_CONSTRUCTOR}
|
@@ -282,7 +286,7 @@ module Teckel
|
|
282
286
|
# result_constructor ->(value, success) { result.new(value, success, {foo: :bar}) }
|
283
287
|
# end
|
284
288
|
def result_constructor(sym_or_proc = nil)
|
285
|
-
|
289
|
+
get_or_set_constructor(:result_constructor, result, sym_or_proc) ||
|
286
290
|
raise(MissingConfigError, "Missing result_constructor config for #{self}")
|
287
291
|
end
|
288
292
|
|
@@ -293,14 +297,15 @@ module Teckel
|
|
293
297
|
#
|
294
298
|
# @!visibility protected
|
295
299
|
# @note Don't use in conjunction with {result} or {result_constructor}
|
296
|
-
# @return [
|
300
|
+
# @return [void]
|
297
301
|
def result!
|
298
|
-
@config.
|
299
|
-
@config.
|
302
|
+
@config.get_or_set(:result, Result)
|
303
|
+
@config.get_or_set(:result_constructor, Result.method(:new))
|
300
304
|
nil
|
301
305
|
end
|
302
306
|
|
303
307
|
# @!visibility private
|
308
|
+
# @return [Array<Symbol>]
|
304
309
|
REQUIRED_CONFIGS = %i[
|
305
310
|
input input_constructor
|
306
311
|
output output_constructor
|
@@ -334,7 +339,7 @@ module Teckel
|
|
334
339
|
# @return [self]
|
335
340
|
# @!visibility public
|
336
341
|
def dup
|
337
|
-
dup_config(super())
|
342
|
+
dup_config(super()) # standard:disable Style/SuperArguments
|
338
343
|
end
|
339
344
|
|
340
345
|
# Produces a clone of this operation and all it's configuration
|
@@ -343,9 +348,9 @@ module Teckel
|
|
343
348
|
# @!visibility public
|
344
349
|
def clone
|
345
350
|
if frozen?
|
346
|
-
super()
|
351
|
+
super() # standard:disable Style/SuperArguments
|
347
352
|
else
|
348
|
-
dup_config(super())
|
353
|
+
dup_config(super()) # standard:disable Style/SuperArguments
|
349
354
|
end
|
350
355
|
end
|
351
356
|
|
@@ -355,7 +360,7 @@ module Teckel
|
|
355
360
|
# @!visibility public
|
356
361
|
def freeze
|
357
362
|
@config.freeze
|
358
|
-
super()
|
363
|
+
super() # standard:disable Style/SuperArguments
|
359
364
|
end
|
360
365
|
|
361
366
|
# @!visibility private
|
@@ -372,22 +377,20 @@ module Teckel
|
|
372
377
|
end
|
373
378
|
end
|
374
379
|
|
375
|
-
private
|
376
|
-
|
377
|
-
def dup_config(other_class)
|
380
|
+
private def dup_config(other_class)
|
378
381
|
other_class.instance_variable_set(:@config, @config.dup)
|
379
382
|
other_class
|
380
383
|
end
|
381
384
|
|
382
|
-
def
|
385
|
+
private def get_or_set_constructor(name, on, sym_or_proc)
|
383
386
|
constructor = build_constructor(on, sym_or_proc)
|
384
387
|
|
385
|
-
@config.
|
388
|
+
@config.get_or_set(name, constructor) {
|
386
389
|
build_constructor(on, DEFAULT_CONSTRUCTOR)
|
387
390
|
}
|
388
391
|
end
|
389
392
|
|
390
|
-
def build_constructor(on, sym_or_proc)
|
393
|
+
private def build_constructor(on, sym_or_proc)
|
391
394
|
case sym_or_proc
|
392
395
|
when Proc
|
393
396
|
sym_or_proc
|