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
|
@@ -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
|
|
@@ -51,27 +51,27 @@ module Teckel
|
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
# @!attribute [r] value
|
|
54
|
-
# @return [
|
|
54
|
+
# @return [Object] the value/payload
|
|
55
55
|
attr_reader :value
|
|
56
56
|
|
|
57
57
|
# Get the error/failure value
|
|
58
|
-
# @yield [
|
|
59
|
-
# @param default [
|
|
60
|
-
# @return [
|
|
61
|
-
def failure(default = nil
|
|
58
|
+
# @yield [Object] If a block is given and this is not a failure result, the value is yielded to the block
|
|
59
|
+
# @param default [Object] return this default value if it's not a failure result
|
|
60
|
+
# @return [Object] the value/payload
|
|
61
|
+
def failure(default = nil)
|
|
62
62
|
return value unless @successful
|
|
63
|
-
return yield(value) if
|
|
63
|
+
return yield(value) if block_given?
|
|
64
64
|
|
|
65
65
|
default
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
# Get the success value
|
|
69
|
-
# @yield [
|
|
70
|
-
# @param default [
|
|
71
|
-
# @return [
|
|
72
|
-
def success(default = nil
|
|
69
|
+
# @yield [Object] If a block is given and this is not a success result, the value is yielded to the block
|
|
70
|
+
# @param default [Object] return this default value if it's not a success result
|
|
71
|
+
# @return [Object] the value/payload
|
|
72
|
+
def success(default = nil)
|
|
73
73
|
return value if @successful
|
|
74
|
-
return yield(value) if
|
|
74
|
+
return yield(value) if block_given?
|
|
75
75
|
|
|
76
76
|
default
|
|
77
77
|
end
|
|
@@ -85,7 +85,7 @@ module Teckel
|
|
|
85
85
|
value
|
|
86
86
|
end
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
alias_method :new, :[]
|
|
89
89
|
end
|
|
90
90
|
end
|
|
91
91
|
end
|
data/lib/teckel/operation.rb
CHANGED
|
@@ -59,11 +59,11 @@ module Teckel
|
|
|
59
59
|
module Operation
|
|
60
60
|
module ClassMethods
|
|
61
61
|
# @!visibility private
|
|
62
|
-
UNDEFINED =
|
|
62
|
+
UNDEFINED = Teckel::UNDEFINED
|
|
63
63
|
|
|
64
64
|
# Invoke the Operation
|
|
65
65
|
#
|
|
66
|
-
# @param input Any form of input your {Teckel::Operation::Config#input input} class can handle via the given
|
|
66
|
+
# @param input [Object,nil] Any form of input your {Teckel::Operation::Config#input input} class can handle via the given
|
|
67
67
|
# {Teckel::Operation::Config#input_constructor input_constructor}
|
|
68
68
|
# @return Either An instance of your defined {Teckel::Operation::Config#error error} class or
|
|
69
69
|
# {Teckel::Operation::Config#output output} class
|
|
@@ -111,7 +111,7 @@ module Teckel
|
|
|
111
111
|
def with(settings)
|
|
112
112
|
runable(settings_constructor.call(settings))
|
|
113
113
|
end
|
|
114
|
-
|
|
114
|
+
alias_method :set, :with
|
|
115
115
|
|
|
116
116
|
# Constructs a Runner instance for {call} and {with}.
|
|
117
117
|
#
|
|
@@ -205,8 +205,8 @@ module Teckel
|
|
|
205
205
|
|
|
206
206
|
def self.included(receiver)
|
|
207
207
|
receiver.class_eval do
|
|
208
|
-
extend
|
|
209
|
-
extend
|
|
208
|
+
extend Config
|
|
209
|
+
extend ClassMethods
|
|
210
210
|
include InstanceMethods
|
|
211
211
|
end
|
|
212
212
|
end
|
data/lib/teckel/result.rb
CHANGED
|
@@ -37,7 +37,7 @@ module Teckel
|
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
# @!attribute [r] value
|
|
40
|
-
# @return [
|
|
40
|
+
# @return [Object] the value/payload
|
|
41
41
|
def value
|
|
42
42
|
raise NotImplementedError, "Result object does not implement `value`"
|
|
43
43
|
end
|
|
@@ -48,15 +48,15 @@ module Teckel
|
|
|
48
48
|
|
|
49
49
|
def deconstruct_keys(keys)
|
|
50
50
|
e = {}
|
|
51
|
-
e[:success] = successful? if keys
|
|
52
|
-
e[:value] = value if keys
|
|
51
|
+
e[:success] = successful? if keys&.include?(:success)
|
|
52
|
+
e[:value] = value if keys&.include?(:value)
|
|
53
53
|
e
|
|
54
54
|
end
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
def self.included(receiver)
|
|
58
58
|
receiver.class_eval do
|
|
59
|
-
extend
|
|
59
|
+
extend ClassMethods
|
|
60
60
|
include InstanceMethods
|
|
61
61
|
end
|
|
62
62
|
end
|
data/lib/teckel/version.rb
CHANGED
data/lib/teckel.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
require_relative "teckel/version"
|
|
4
4
|
|
|
5
5
|
module Teckel
|
|
6
6
|
# Base error class for this lib
|
|
@@ -13,6 +13,9 @@ module Teckel
|
|
|
13
13
|
class MissingConfigError < Teckel::Error; end
|
|
14
14
|
|
|
15
15
|
DEFAULT_CONSTRUCTOR = :[]
|
|
16
|
+
|
|
17
|
+
# @!visibility private
|
|
18
|
+
UNDEFINED = Object.new.freeze
|
|
16
19
|
end
|
|
17
20
|
|
|
18
21
|
require_relative "teckel/config"
|
metadata
CHANGED
|
@@ -1,27 +1,26 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: teckel
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.10.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Robert Schulze
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: bundler
|
|
15
14
|
requirement: !ruby/object:Gem::Requirement
|
|
16
15
|
requirements:
|
|
17
|
-
- - "
|
|
16
|
+
- - ">="
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
18
|
version: '2.0'
|
|
20
19
|
type: :development
|
|
21
20
|
prerelease: false
|
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
22
|
requirements:
|
|
24
|
-
- - "
|
|
23
|
+
- - ">="
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
25
|
version: '2.0'
|
|
27
26
|
- !ruby/object:Gem::Dependency
|
|
@@ -66,6 +65,20 @@ dependencies:
|
|
|
66
65
|
- - ">="
|
|
67
66
|
- !ruby/object:Gem::Version
|
|
68
67
|
version: '0'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: standard
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
69
82
|
- !ruby/object:Gem::Dependency
|
|
70
83
|
name: yard
|
|
71
84
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -121,29 +134,6 @@ files:
|
|
|
121
134
|
- lib/teckel/operation/runner.rb
|
|
122
135
|
- lib/teckel/result.rb
|
|
123
136
|
- lib/teckel/version.rb
|
|
124
|
-
- spec/chain/around_hook_spec.rb
|
|
125
|
-
- spec/chain/default_settings_spec.rb
|
|
126
|
-
- spec/chain/inheritance_spec.rb
|
|
127
|
-
- spec/chain/none_input_spec.rb
|
|
128
|
-
- spec/chain/results_spec.rb
|
|
129
|
-
- spec/chain_spec.rb
|
|
130
|
-
- spec/config_spec.rb
|
|
131
|
-
- spec/doctest_helper.rb
|
|
132
|
-
- spec/operation/config_spec.rb
|
|
133
|
-
- spec/operation/contract_trace_spec.rb
|
|
134
|
-
- spec/operation/default_settings_spec.rb
|
|
135
|
-
- spec/operation/fail_on_input_spec.rb
|
|
136
|
-
- spec/operation/inheritance_spec.rb
|
|
137
|
-
- spec/operation/result_spec.rb
|
|
138
|
-
- spec/operation/results_spec.rb
|
|
139
|
-
- spec/operation_spec.rb
|
|
140
|
-
- spec/rb27/pattern_matching_spec.rb
|
|
141
|
-
- spec/result_spec.rb
|
|
142
|
-
- spec/spec_helper.rb
|
|
143
|
-
- spec/support/dry_base.rb
|
|
144
|
-
- spec/support/fake_db.rb
|
|
145
|
-
- spec/support/fake_models.rb
|
|
146
|
-
- spec/teckel_spec.rb
|
|
147
137
|
homepage: https://github.com/fnordfish/teckel
|
|
148
138
|
licenses:
|
|
149
139
|
- Apache-2.0
|
|
@@ -151,9 +141,8 @@ metadata:
|
|
|
151
141
|
changelog_uri: https://github.com/fnordfish/teckel/blob/main/CHANGELOG.md
|
|
152
142
|
source_code_uri: https://github.com/fnordfish/teckel
|
|
153
143
|
bug_tracker_uri: https://github.com/fnordfish/teckel/issues
|
|
154
|
-
documentation_uri: https://www.rubydoc.info/gems/teckel/0.
|
|
144
|
+
documentation_uri: https://www.rubydoc.info/gems/teckel/0.10.0
|
|
155
145
|
user_docs_uri: https://fnordfish.github.io/teckel/
|
|
156
|
-
post_install_message:
|
|
157
146
|
rdoc_options: []
|
|
158
147
|
require_paths:
|
|
159
148
|
- lib
|
|
@@ -168,31 +157,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
168
157
|
- !ruby/object:Gem::Version
|
|
169
158
|
version: '0'
|
|
170
159
|
requirements: []
|
|
171
|
-
rubygems_version:
|
|
172
|
-
signing_key:
|
|
160
|
+
rubygems_version: 4.0.9
|
|
173
161
|
specification_version: 4
|
|
174
162
|
summary: Operations with enforced in/out/err data structures
|
|
175
|
-
test_files:
|
|
176
|
-
- spec/chain/around_hook_spec.rb
|
|
177
|
-
- spec/chain/default_settings_spec.rb
|
|
178
|
-
- spec/chain/inheritance_spec.rb
|
|
179
|
-
- spec/chain/none_input_spec.rb
|
|
180
|
-
- spec/chain/results_spec.rb
|
|
181
|
-
- spec/chain_spec.rb
|
|
182
|
-
- spec/config_spec.rb
|
|
183
|
-
- spec/doctest_helper.rb
|
|
184
|
-
- spec/operation/config_spec.rb
|
|
185
|
-
- spec/operation/contract_trace_spec.rb
|
|
186
|
-
- spec/operation/default_settings_spec.rb
|
|
187
|
-
- spec/operation/fail_on_input_spec.rb
|
|
188
|
-
- spec/operation/inheritance_spec.rb
|
|
189
|
-
- spec/operation/result_spec.rb
|
|
190
|
-
- spec/operation/results_spec.rb
|
|
191
|
-
- spec/operation_spec.rb
|
|
192
|
-
- spec/rb27/pattern_matching_spec.rb
|
|
193
|
-
- spec/result_spec.rb
|
|
194
|
-
- spec/spec_helper.rb
|
|
195
|
-
- spec/support/dry_base.rb
|
|
196
|
-
- spec/support/fake_db.rb
|
|
197
|
-
- spec/support/fake_models.rb
|
|
198
|
-
- spec/teckel_spec.rb
|
|
163
|
+
test_files: []
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'support/dry_base'
|
|
4
|
-
require 'support/fake_db'
|
|
5
|
-
require 'support/fake_models'
|
|
6
|
-
|
|
7
|
-
module TeckelChainAroundHookTest
|
|
8
|
-
class CreateUser
|
|
9
|
-
include ::Teckel::Operation
|
|
10
|
-
|
|
11
|
-
result!
|
|
12
|
-
|
|
13
|
-
input Types::Hash.schema(name: Types::String, age: Types::Coercible::Integer.optional)
|
|
14
|
-
output Types.Instance(User)
|
|
15
|
-
error Types::Hash.schema(message: Types::String, errors: Types::Array.of(Types::Hash))
|
|
16
|
-
|
|
17
|
-
def call(input)
|
|
18
|
-
user = User.new(name: input[:name], age: input[:age])
|
|
19
|
-
if user.save
|
|
20
|
-
success!(user)
|
|
21
|
-
else
|
|
22
|
-
fail!(message: "Could not safe User", errors: user.errors)
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
class AddFriend
|
|
28
|
-
include ::Teckel::Operation
|
|
29
|
-
|
|
30
|
-
result!
|
|
31
|
-
|
|
32
|
-
settings Struct.new(:fail_befriend)
|
|
33
|
-
|
|
34
|
-
input Types.Instance(User)
|
|
35
|
-
output Types::Hash.schema(user: Types.Instance(User), friend: Types.Instance(User))
|
|
36
|
-
error Types::Hash.schema(message: Types::String)
|
|
37
|
-
|
|
38
|
-
def call(user)
|
|
39
|
-
if settings&.fail_befriend
|
|
40
|
-
fail!(message: "Did not find a friend.")
|
|
41
|
-
else
|
|
42
|
-
success! user: user, friend: User.new(name: "A friend", age: 42)
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
@stack = []
|
|
48
|
-
def self.stack
|
|
49
|
-
@stack
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
class Chain
|
|
53
|
-
include Teckel::Chain
|
|
54
|
-
|
|
55
|
-
around ->(chain, input) {
|
|
56
|
-
result = nil
|
|
57
|
-
begin
|
|
58
|
-
TeckelChainAroundHookTest.stack << :before
|
|
59
|
-
|
|
60
|
-
FakeDB.transaction do
|
|
61
|
-
result = chain.call(input)
|
|
62
|
-
raise FakeDB::Rollback if result.failure?
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
TeckelChainAroundHookTest.stack << :after
|
|
66
|
-
result
|
|
67
|
-
rescue FakeDB::Rollback
|
|
68
|
-
result
|
|
69
|
-
end
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
step :create, CreateUser
|
|
73
|
-
step :befriend, AddFriend
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
RSpec.describe Teckel::Chain do
|
|
78
|
-
before { TeckelChainAroundHookTest.stack.clear }
|
|
79
|
-
|
|
80
|
-
context "success" do
|
|
81
|
-
it "result matches" do
|
|
82
|
-
result = TeckelChainAroundHookTest::Chain.call(name: "Bob", age: 23)
|
|
83
|
-
expect(result.success).to include(user: kind_of(User), friend: kind_of(User))
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
it "runs around hook" do
|
|
87
|
-
TeckelChainAroundHookTest::Chain.call(name: "Bob", age: 23)
|
|
88
|
-
expect(TeckelChainAroundHookTest.stack).to eq([:before, :after])
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
context "failure" do
|
|
93
|
-
it "runs around hook" do
|
|
94
|
-
TeckelChainAroundHookTest::Chain.
|
|
95
|
-
with(befriend: :fail).
|
|
96
|
-
call(name: "Bob", age: 23)
|
|
97
|
-
expect(TeckelChainAroundHookTest.stack).to eq([:before])
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
end
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module TeckelChainDefaultSettingsTest
|
|
4
|
-
class MyOperation
|
|
5
|
-
include Teckel::Operation
|
|
6
|
-
result!
|
|
7
|
-
|
|
8
|
-
settings Struct.new(:say, :other)
|
|
9
|
-
settings_constructor ->(data) { settings.new(*data.values_at(*settings.members)) } # ruby 2.4 way for `keyword_init: true`
|
|
10
|
-
|
|
11
|
-
input none
|
|
12
|
-
output Hash
|
|
13
|
-
error none
|
|
14
|
-
|
|
15
|
-
def call(_)
|
|
16
|
-
success! settings.to_h
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
class Chain
|
|
21
|
-
include Teckel::Chain
|
|
22
|
-
|
|
23
|
-
default_settings!(a: { say: "Chain Default" })
|
|
24
|
-
|
|
25
|
-
step :a, MyOperation
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
RSpec.describe Teckel::Chain do
|
|
30
|
-
specify "call chain without settings, uses default settings" do
|
|
31
|
-
result = TeckelChainDefaultSettingsTest::Chain.call
|
|
32
|
-
expect(result.success).to eq(say: "Chain Default", other: nil)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
specify "call chain with explicit settings, overwrites defaults" do
|
|
36
|
-
result = TeckelChainDefaultSettingsTest::Chain.with(a: { other: "What" }).call
|
|
37
|
-
expect(result.success).to eq(say: nil, other: "What")
|
|
38
|
-
end
|
|
39
|
-
end
|