bcdd-result 0.10.0 → 0.12.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 +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
|