bcdd-result 0.10.0 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +60 -15
- data/README.md +326 -67
- data/Rakefile +8 -2
- data/lib/bcdd/result/callable_and_then/caller.rb +49 -0
- data/lib/bcdd/result/callable_and_then/config.rb +15 -0
- data/lib/bcdd/result/callable_and_then/error.rb +11 -0
- data/lib/bcdd/result/callable_and_then.rb +9 -0
- data/lib/bcdd/result/config/switchers/addons.rb +9 -4
- data/lib/bcdd/result/config/switchers/features.rb +5 -1
- data/lib/bcdd/result/config.rb +9 -3
- data/lib/bcdd/result/context/callable_and_then.rb +39 -0
- data/lib/bcdd/result/context/expectations/mixin.rb +11 -3
- data/lib/bcdd/result/context/mixin.rb +13 -5
- data/lib/bcdd/result/context/success.rb +12 -8
- data/lib/bcdd/result/context.rb +34 -16
- data/lib/bcdd/result/error.rb +20 -11
- data/lib/bcdd/result/expectations/mixin.rb +12 -6
- data/lib/bcdd/result/expectations.rb +7 -7
- data/lib/bcdd/result/mixin.rb +11 -5
- data/lib/bcdd/result/transitions/tracking/disabled.rb +14 -4
- data/lib/bcdd/result/transitions/tracking/enabled.rb +38 -18
- data/lib/bcdd/result/transitions/tree.rb +10 -6
- data/lib/bcdd/result/transitions.rb +8 -10
- data/lib/bcdd/result/version.rb +1 -1
- data/lib/bcdd/result.rb +38 -23
- data/sig/bcdd/result/callable_and_then.rbs +60 -0
- data/sig/bcdd/result/config.rbs +3 -0
- data/sig/bcdd/result/context.rbs +73 -9
- data/sig/bcdd/result/error.rbs +9 -6
- data/sig/bcdd/result/expectations.rbs +12 -8
- data/sig/bcdd/result/mixin.rbs +10 -2
- data/sig/bcdd/result/transitions.rbs +16 -5
- data/sig/bcdd/result.rbs +12 -8
- metadata +8 -2
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result
|
4
|
+
class CallableAndThen::Caller
|
5
|
+
def self.call(source, value:, injected_value:, method_name:)
|
6
|
+
method = callable_method(source, method_name)
|
7
|
+
|
8
|
+
Transitions.tracking.record_and_then(method, injected_value, source) do
|
9
|
+
result =
|
10
|
+
if source.is_a?(::Proc)
|
11
|
+
call_proc!(source, value, injected_value)
|
12
|
+
else
|
13
|
+
call_method!(source, method, value, injected_value)
|
14
|
+
end
|
15
|
+
|
16
|
+
ensure_result_object(source, value, result)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.call_proc!(source, value, injected_value)
|
21
|
+
case source.arity
|
22
|
+
when 1 then source.call(value)
|
23
|
+
when 2 then source.call(value, injected_value)
|
24
|
+
else raise CallableAndThen::Error::InvalidArity.build(source: source, method: :call, arity: '1..2')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.call_method!(source, method, value, injected_value)
|
29
|
+
case method.arity
|
30
|
+
when 1 then source.send(method.name, value)
|
31
|
+
when 2 then source.send(method.name, value, injected_value)
|
32
|
+
else raise CallableAndThen::Error::InvalidArity.build(source: source, method: method.name, arity: '1..2')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.callable_method(source, method_name)
|
37
|
+
source.method(method_name || Config.instance.and_then!.default_method_name_to_call)
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.ensure_result_object(source, _value, result)
|
41
|
+
return result if result.is_a?(::BCDD::Result)
|
42
|
+
|
43
|
+
raise Error::UnexpectedOutcome.build(outcome: result, origin: source)
|
44
|
+
end
|
45
|
+
|
46
|
+
private_class_method :new, :allocate
|
47
|
+
private_class_method :call_proc!, :call_method!, :callable_method, :ensure_result_object
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result
|
4
|
+
class CallableAndThen::Config
|
5
|
+
attr_accessor :default_method_name_to_call
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
self.default_method_name_to_call = :call
|
9
|
+
end
|
10
|
+
|
11
|
+
def options
|
12
|
+
{ default_method_name_to_call: default_method_name_to_call }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result
|
4
|
+
class CallableAndThen::Error < Error
|
5
|
+
class InvalidArity < self
|
6
|
+
def self.build(source:, method:, arity:)
|
7
|
+
new("Invalid arity for #{source.class}##{method} method. Expected arity: #{arity}")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -3,11 +3,16 @@
|
|
3
3
|
class BCDD::Result
|
4
4
|
class Config
|
5
5
|
module Addons
|
6
|
+
AFFECTS = %w[
|
7
|
+
BCDD::Result.mixin
|
8
|
+
BCDD::Result::Context.mixin
|
9
|
+
BCDD::Result::Expectations.mixin
|
10
|
+
BCDD::Result::Context::Expectations.mixin
|
11
|
+
].freeze
|
12
|
+
|
6
13
|
OPTIONS = {
|
7
|
-
continue: {
|
8
|
-
|
9
|
-
affects: %w[BCDD::Result BCDD::Result::Context BCDD::Result::Expectations BCDD::Result::Context::Expectations]
|
10
|
-
}
|
14
|
+
continue: { default: false, affects: AFFECTS },
|
15
|
+
given: { default: true, affects: AFFECTS }
|
11
16
|
}.transform_values!(&:freeze).freeze
|
12
17
|
|
13
18
|
def self.switcher
|
@@ -10,7 +10,11 @@ class BCDD::Result
|
|
10
10
|
},
|
11
11
|
transitions: {
|
12
12
|
default: true,
|
13
|
-
affects: %w[BCDD::Result BCDD::Result::Context]
|
13
|
+
affects: %w[BCDD::Result BCDD::Result::Context BCDD::Result::Expectations BCDD::Result::Context::Expectations]
|
14
|
+
},
|
15
|
+
and_then!: {
|
16
|
+
default: false,
|
17
|
+
affects: %w[BCDD::Result BCDD::Result::Context BCDD::Result::Expectations BCDD::Result::Context::Expectations]
|
14
18
|
}
|
15
19
|
}.transform_values!(&:freeze).freeze
|
16
20
|
|
data/lib/bcdd/result/config.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'singleton'
|
4
|
-
|
5
3
|
require_relative 'config/options'
|
6
4
|
require_relative 'config/switcher'
|
7
5
|
require_relative 'config/switchers/addons'
|
@@ -20,6 +18,11 @@ class BCDD::Result
|
|
20
18
|
@feature = Features.switcher
|
21
19
|
@constant_alias = ConstantAliases.switcher
|
22
20
|
@pattern_matching = PatternMatching.switcher
|
21
|
+
@and_then_ = CallableAndThen::Config.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def and_then!
|
25
|
+
@and_then_
|
23
26
|
end
|
24
27
|
|
25
28
|
def freeze
|
@@ -27,6 +30,7 @@ class BCDD::Result
|
|
27
30
|
feature.freeze
|
28
31
|
constant_alias.freeze
|
29
32
|
pattern_matching.freeze
|
33
|
+
and_then!.freeze
|
30
34
|
|
31
35
|
super
|
32
36
|
end
|
@@ -45,7 +49,9 @@ class BCDD::Result
|
|
45
49
|
end
|
46
50
|
|
47
51
|
def inspect
|
48
|
-
"#<#{self.class.name}
|
52
|
+
"#<#{self.class.name} " \
|
53
|
+
"options=#{options.keys.sort.inspect} " \
|
54
|
+
"and_then!=#{and_then!.options.inspect}>"
|
49
55
|
end
|
50
56
|
end
|
51
57
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result
|
4
|
+
module Context::CallableAndThen
|
5
|
+
class Caller < CallableAndThen::Caller
|
6
|
+
module KeyArgs
|
7
|
+
def self.parameters?(source)
|
8
|
+
parameters = source.parameters.map(&:first)
|
9
|
+
|
10
|
+
!parameters.empty? && parameters.all?(/\Akey/)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.invalid_arity(source, method)
|
14
|
+
CallableAndThen::Error::InvalidArity.build(source: source, method: method, arity: 'only keyword args')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.call_proc!(source, value, _injected_value)
|
19
|
+
return source.call(**value) if KeyArgs.parameters?(source)
|
20
|
+
|
21
|
+
raise KeyArgs.invalid_arity(source, :call)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.call_method!(source, method, value, _injected_value)
|
25
|
+
return source.send(method.name, **value) if KeyArgs.parameters?(method)
|
26
|
+
|
27
|
+
raise KeyArgs.invalid_arity(source, method.name)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.ensure_result_object(source, value, result)
|
31
|
+
return result.tap { result.send(:acc).then { _1.merge!(value.merge(_1)) } } if result.is_a?(Context)
|
32
|
+
|
33
|
+
raise Error::UnexpectedOutcome.build(outcome: result, origin: source, expected: Context::EXPECTED_OUTCOME)
|
34
|
+
end
|
35
|
+
|
36
|
+
private_class_method :call_proc!, :call_method!
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -7,13 +7,21 @@ class BCDD::Result::Context
|
|
7
7
|
Methods = BCDD::Result::Expectations::Mixin::Methods
|
8
8
|
|
9
9
|
module Addons
|
10
|
-
module
|
10
|
+
module Continue
|
11
11
|
private def Continue(**value)
|
12
|
-
Success.new(type: :continued, value: value,
|
12
|
+
Success.new(type: :continued, value: value, source: self)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
|
16
|
+
module Given
|
17
|
+
private def Given(*values)
|
18
|
+
value = values.map(&:to_h).reduce({}) { |acc, val| acc.merge(val) }
|
19
|
+
|
20
|
+
Success.new(type: :given, value: value, source: self)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
OPTIONS = { continue: Continue, given: Given }.freeze
|
17
25
|
|
18
26
|
def self.options(config_flags)
|
19
27
|
::BCDD::Result::Config::Options.addon(map: config_flags, from: OPTIONS)
|
@@ -13,15 +13,15 @@ class BCDD::Result::Context
|
|
13
13
|
_ResultAs(Failure, type, value)
|
14
14
|
end
|
15
15
|
|
16
|
-
private def _ResultAs(kind_class, type, value,
|
17
|
-
kind_class.new(type: type, value: value,
|
16
|
+
private def _ResultAs(kind_class, type, value, terminal: nil)
|
17
|
+
kind_class.new(type: type, value: value, source: self, terminal: terminal)
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
21
|
module Addons
|
22
|
-
module
|
22
|
+
module Continue
|
23
23
|
def Success(type, **value)
|
24
|
-
_ResultAs(Success, type, value,
|
24
|
+
_ResultAs(Success, type, value, terminal: true)
|
25
25
|
end
|
26
26
|
|
27
27
|
private def Continue(**value)
|
@@ -29,7 +29,15 @@ class BCDD::Result::Context
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
|
32
|
+
module Given
|
33
|
+
private def Given(*values)
|
34
|
+
value = values.map(&:to_h).reduce({}) { |acc, val| acc.merge(val) }
|
35
|
+
|
36
|
+
_ResultAs(Success, :given, value)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
OPTIONS = { continue: Continue, given: Given }.freeze
|
33
41
|
|
34
42
|
def self.options(config_flags)
|
35
43
|
::BCDD::Result::Config::Options.addon(map: config_flags, from: OPTIONS)
|
@@ -1,15 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
class BCDD::Result
|
4
|
-
|
3
|
+
class BCDD::Result
|
4
|
+
class Context::Success < Context
|
5
|
+
include ::BCDD::Result::Success::Methods
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
def and_expose(type, keys, terminal: true)
|
8
|
+
unless keys.is_a?(::Array) && !keys.empty? && keys.all?(::Symbol)
|
9
|
+
raise ::ArgumentError, 'keys must be an Array of Symbols'
|
10
|
+
end
|
11
|
+
|
12
|
+
Transitions.tracking.reset_and_then!
|
10
13
|
|
11
|
-
|
14
|
+
exposed_value = acc.merge(value).slice(*keys)
|
12
15
|
|
13
|
-
|
16
|
+
self.class.new(type: type, value: exposed_value, source: source, terminal: terminal)
|
17
|
+
end
|
14
18
|
end
|
15
19
|
end
|
data/lib/bcdd/result/context.rb
CHANGED
@@ -6,6 +6,9 @@ class BCDD::Result
|
|
6
6
|
require_relative 'context/success'
|
7
7
|
require_relative 'context/mixin'
|
8
8
|
require_relative 'context/expectations'
|
9
|
+
require_relative 'context/callable_and_then'
|
10
|
+
|
11
|
+
EXPECTED_OUTCOME = 'BCDD::Result::Context::Success or BCDD::Result::Context::Failure'
|
9
12
|
|
10
13
|
def self.Success(type, **value)
|
11
14
|
Success.new(type: type, value: value)
|
@@ -15,7 +18,7 @@ class BCDD::Result
|
|
15
18
|
Failure.new(type: type, value: value)
|
16
19
|
end
|
17
20
|
|
18
|
-
def initialize(type:, value:,
|
21
|
+
def initialize(type:, value:, source: nil, expectations: nil, terminal: nil)
|
19
22
|
value.is_a?(::Hash) or raise ::ArgumentError, 'value must be a Hash'
|
20
23
|
|
21
24
|
@acc = {}
|
@@ -23,8 +26,16 @@ class BCDD::Result
|
|
23
26
|
super
|
24
27
|
end
|
25
28
|
|
26
|
-
def and_then(method_name = nil, **
|
27
|
-
super(method_name,
|
29
|
+
def and_then(method_name = nil, **injected_value, &block)
|
30
|
+
super(method_name, injected_value, &block)
|
31
|
+
end
|
32
|
+
|
33
|
+
def and_then!(source, **injected_value)
|
34
|
+
_call = injected_value.delete(:_call)
|
35
|
+
|
36
|
+
acc.merge!(injected_value)
|
37
|
+
|
38
|
+
super(source, injected_value, _call: _call)
|
28
39
|
end
|
29
40
|
|
30
41
|
protected
|
@@ -33,20 +44,23 @@ class BCDD::Result
|
|
33
44
|
|
34
45
|
private
|
35
46
|
|
36
|
-
|
47
|
+
SourceMethodArity = ->(method) do
|
37
48
|
return 0 if method.arity.zero?
|
38
|
-
|
49
|
+
|
50
|
+
parameters = method.parameters.map(&:first)
|
51
|
+
|
52
|
+
return 1 if !parameters.empty? && parameters.all?(/\Akey/)
|
39
53
|
|
40
54
|
-1
|
41
55
|
end
|
42
56
|
|
43
|
-
def
|
44
|
-
acc.merge!(value.merge(
|
57
|
+
def call_and_then_source_method!(method, injected_value)
|
58
|
+
acc.merge!(value.merge(injected_value))
|
45
59
|
|
46
|
-
case
|
47
|
-
when 0 then
|
48
|
-
when 1 then
|
49
|
-
else raise Error::
|
60
|
+
case SourceMethodArity[method]
|
61
|
+
when 0 then source.send(method.name)
|
62
|
+
when 1 then source.send(method.name, **acc)
|
63
|
+
else raise Error::InvalidSourceMethodArity.build(source: source, method: method, max_arity: 1)
|
50
64
|
end
|
51
65
|
end
|
52
66
|
|
@@ -56,20 +70,24 @@ class BCDD::Result
|
|
56
70
|
block.call(acc)
|
57
71
|
end
|
58
72
|
|
73
|
+
def call_and_then_callable!(source, value:, injected_value:, method_name:)
|
74
|
+
acc.merge!(value.merge(injected_value))
|
75
|
+
|
76
|
+
CallableAndThen::Caller.call(source, value: acc, injected_value: injected_value, method_name: method_name)
|
77
|
+
end
|
78
|
+
|
59
79
|
def ensure_result_object(result, origin:)
|
60
80
|
raise_unexpected_outcome_error(result, origin) unless result.is_a?(Context)
|
61
81
|
|
62
|
-
return result.tap { _1.acc.merge!(acc) } if result.
|
82
|
+
return result.tap { _1.acc.merge!(acc) } if result.source.equal?(source)
|
63
83
|
|
64
|
-
raise Error::
|
84
|
+
raise Error::InvalidResultSource.build(given_result: result, expected_source: source)
|
65
85
|
end
|
66
86
|
|
67
|
-
EXPECTED_OUTCOME = 'BCDD::Result::Context::Success or BCDD::Result::Context::Failure'
|
68
|
-
|
69
87
|
def raise_unexpected_outcome_error(result, origin)
|
70
88
|
raise Error::UnexpectedOutcome.build(outcome: result, origin: origin, expected: EXPECTED_OUTCOME)
|
71
89
|
end
|
72
90
|
|
73
|
-
private_constant :
|
91
|
+
private_constant :SourceMethodArity
|
74
92
|
end
|
75
93
|
end
|
data/lib/bcdd/result/error.rb
CHANGED
@@ -9,7 +9,7 @@ class BCDD::Result::Error < StandardError
|
|
9
9
|
end
|
10
10
|
|
11
11
|
class MissingTypeArgument < self
|
12
|
-
def initialize(
|
12
|
+
def initialize(_message = nil)
|
13
13
|
super('A type (argument) is required to invoke the #on/#on_type method')
|
14
14
|
end
|
15
15
|
end
|
@@ -22,29 +22,38 @@ class BCDD::Result::Error < StandardError
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
class
|
26
|
-
def self.build(given_result:,
|
25
|
+
class InvalidResultSource < self
|
26
|
+
def self.build(given_result:, expected_source:)
|
27
27
|
message =
|
28
|
-
"You cannot call #and_then and return a result that does not belong to the
|
29
|
-
"Expected
|
30
|
-
"Given
|
28
|
+
"You cannot call #and_then and return a result that does not belong to the same source!\n" \
|
29
|
+
"Expected source: #{expected_source.inspect}\n" \
|
30
|
+
"Given source: #{given_result.send(:source).inspect}\n" \
|
31
31
|
"Given result: #{given_result.inspect}"
|
32
32
|
|
33
33
|
new(message)
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
class
|
38
|
-
def self.build(
|
39
|
-
new("#{
|
37
|
+
class InvalidSourceMethodArity < self
|
38
|
+
def self.build(source:, method:, max_arity:)
|
39
|
+
new("#{source.class}##{method.name} has unsupported arity (#{method.arity}). Expected 0..#{max_arity}")
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
43
|
class UnhandledTypes < self
|
44
44
|
def self.build(types:)
|
45
|
-
|
45
|
+
source = types.size == 1 ? 'This was' : 'These were'
|
46
46
|
|
47
|
-
new("You must handle all cases. #{
|
47
|
+
new("You must handle all cases. #{source} not handled: #{types.map(&:inspect).join(', ')}")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class CallableAndThenDisabled < self
|
52
|
+
def initialize(_message = nil)
|
53
|
+
super(
|
54
|
+
'You cannot use #and_then! as the feature is disabled. ' \
|
55
|
+
'Please use BCDD::Result.config.feature.enable!(:and_then!) to enable it.'
|
56
|
+
)
|
48
57
|
end
|
49
58
|
end
|
50
59
|
end
|
@@ -24,25 +24,31 @@ class BCDD::Result
|
|
24
24
|
|
25
25
|
FACTORY = <<~RUBY
|
26
26
|
private def _Result
|
27
|
-
@_Result ||= Result.with(
|
27
|
+
@_Result ||= Result.with(source: self, terminal: %<terminal>s)
|
28
28
|
end
|
29
29
|
RUBY
|
30
30
|
|
31
31
|
def self.to_eval(addons)
|
32
|
-
|
32
|
+
terminal = addons.key?(:continue) ? 'true' : 'nil'
|
33
33
|
|
34
|
-
"#{BASE}\n#{format(FACTORY,
|
34
|
+
"#{BASE}\n#{format(FACTORY, terminal: terminal)}"
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
module Addons
|
39
|
-
module
|
39
|
+
module Continue
|
40
40
|
private def Continue(value)
|
41
|
-
Success.new(type: :continued, value: value,
|
41
|
+
Success.new(type: :continued, value: value, source: self)
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
-
|
45
|
+
module Given
|
46
|
+
private def Given(value)
|
47
|
+
Success.new(type: :given, value: value, source: self)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
OPTIONS = { continue: Continue, given: Given }.freeze
|
46
52
|
|
47
53
|
def self.options(config_flags)
|
48
54
|
Config::Options.addon(map: config_flags, from: OPTIONS)
|
@@ -38,10 +38,10 @@ class BCDD::Result
|
|
38
38
|
|
39
39
|
private_class_method :mixin!, :mixin_module, :result_factory_without_expectations
|
40
40
|
|
41
|
-
def initialize(
|
42
|
-
@
|
41
|
+
def initialize(source: nil, contract: nil, terminal: nil, **options)
|
42
|
+
@terminal = terminal
|
43
43
|
|
44
|
-
@
|
44
|
+
@source = source
|
45
45
|
|
46
46
|
@contract = contract if contract.is_a?(Contract::Evaluator)
|
47
47
|
|
@@ -60,16 +60,16 @@ class BCDD::Result
|
|
60
60
|
_ResultAs(Failure, type, value)
|
61
61
|
end
|
62
62
|
|
63
|
-
def with(
|
64
|
-
self.class.new(
|
63
|
+
def with(source:, terminal: nil)
|
64
|
+
self.class.new(source: source, terminal: terminal, contract: contract)
|
65
65
|
end
|
66
66
|
|
67
67
|
private
|
68
68
|
|
69
69
|
def _ResultAs(kind_class, type, value)
|
70
|
-
kind_class.new(type: type, value: value,
|
70
|
+
kind_class.new(type: type, value: value, source: source, expectations: contract, terminal: terminal)
|
71
71
|
end
|
72
72
|
|
73
|
-
attr_reader :
|
73
|
+
attr_reader :source, :terminal, :contract
|
74
74
|
end
|
75
75
|
end
|
data/lib/bcdd/result/mixin.rb
CHANGED
@@ -20,15 +20,15 @@ class BCDD::Result
|
|
20
20
|
_ResultAs(Failure, type, value)
|
21
21
|
end
|
22
22
|
|
23
|
-
private def _ResultAs(kind_class, type, value,
|
24
|
-
kind_class.new(type: type, value: value,
|
23
|
+
private def _ResultAs(kind_class, type, value, terminal: nil)
|
24
|
+
kind_class.new(type: type, value: value, source: self, terminal: terminal)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
28
|
module Addons
|
29
|
-
module
|
29
|
+
module Continue
|
30
30
|
def Success(type, value = nil)
|
31
|
-
_ResultAs(Success, type, value,
|
31
|
+
_ResultAs(Success, type, value, terminal: true)
|
32
32
|
end
|
33
33
|
|
34
34
|
private def Continue(value)
|
@@ -36,7 +36,13 @@ class BCDD::Result
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
|
39
|
+
module Given
|
40
|
+
private def Given(value)
|
41
|
+
_ResultAs(Success, :given, value)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
OPTIONS = { continue: Continue, given: Given }.freeze
|
40
46
|
|
41
47
|
def self.options(config_flags)
|
42
48
|
Config::Options.addon(map: config_flags, from: OPTIONS)
|
@@ -2,16 +2,26 @@
|
|
2
2
|
|
3
3
|
module BCDD::Result::Transitions
|
4
4
|
module Tracking::Disabled
|
5
|
-
def self.
|
6
|
-
|
7
|
-
|
5
|
+
def self.exec(_name, _desc)
|
6
|
+
EnsureResult[yield]
|
7
|
+
end
|
8
8
|
|
9
9
|
def self.reset!; end
|
10
10
|
|
11
11
|
def self.record(result); end
|
12
12
|
|
13
|
-
def self.record_and_then(_type, _data,
|
13
|
+
def self.record_and_then(_type, _data, _source)
|
14
14
|
yield
|
15
15
|
end
|
16
|
+
|
17
|
+
def self.reset_and_then!; end
|
18
|
+
|
19
|
+
class << self
|
20
|
+
private
|
21
|
+
|
22
|
+
def start(name, desc); end
|
23
|
+
|
24
|
+
def finish(result); end
|
25
|
+
end
|
16
26
|
end
|
17
27
|
end
|