bcdd-result 0.13.0 → 1.0.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/.rubocop.yml +4 -4
- data/CHANGELOG.md +46 -17
- data/README.md +381 -220
- data/Rakefile +1 -1
- data/Steepfile +1 -1
- data/examples/multiple_listeners/Rakefile +8 -8
- data/examples/multiple_listeners/app/models/account/owner_creation.rb +1 -1
- data/examples/multiple_listeners/app/models/user/creation.rb +1 -1
- data/examples/multiple_listeners/app/models/user/token/creation.rb +1 -1
- data/examples/multiple_listeners/config/initializers/bcdd.rb +0 -2
- data/examples/multiple_listeners/config.rb +3 -3
- data/examples/multiple_listeners/db/setup.rb +2 -3
- data/examples/multiple_listeners/lib/bcdd/result/event_logs_record.rb +27 -0
- data/examples/multiple_listeners/lib/event_logs_listener/stdout.rb +60 -0
- data/examples/multiple_listeners/lib/runtime_breaker.rb +1 -1
- data/examples/service_objects/Rakefile +36 -0
- data/examples/service_objects/app/models/account/member.rb +10 -0
- data/examples/service_objects/app/models/account.rb +11 -0
- data/examples/service_objects/app/models/user/token.rb +7 -0
- data/examples/service_objects/app/models/user.rb +15 -0
- data/examples/service_objects/app/services/account/owner_creation.rb +47 -0
- data/examples/service_objects/app/services/application_service.rb +79 -0
- data/examples/service_objects/app/services/user/creation.rb +56 -0
- data/examples/service_objects/app/services/user/token/creation.rb +37 -0
- data/examples/service_objects/config/boot.rb +17 -0
- data/examples/service_objects/config/initializers/bcdd.rb +9 -0
- data/examples/service_objects/config.rb +20 -0
- data/examples/service_objects/db/setup.rb +49 -0
- data/examples/single_listener/Rakefile +5 -5
- data/examples/single_listener/app/models/account/owner_creation.rb +1 -1
- data/examples/single_listener/app/models/user/creation.rb +1 -1
- data/examples/single_listener/app/models/user/token/creation.rb +1 -1
- data/examples/single_listener/config/initializers/bcdd.rb +0 -2
- data/examples/single_listener/config.rb +1 -1
- data/examples/single_listener/lib/{single_transitions_listener.rb → single_event_logs_listener.rb} +32 -23
- data/lib/bcdd/{result/context → context}/callable_and_then.rb +5 -4
- data/lib/bcdd/{result/context → context}/expectations/mixin.rb +1 -1
- data/lib/bcdd/{result/context → context}/expectations.rb +2 -2
- data/lib/bcdd/context/failure.rb +9 -0
- data/lib/bcdd/{result/context → context}/mixin.rb +2 -2
- data/lib/bcdd/{result/context → context}/success.rb +6 -6
- data/lib/bcdd/context.rb +91 -0
- data/lib/bcdd/failure.rb +23 -0
- data/lib/bcdd/result/_self.rb +198 -0
- data/lib/bcdd/result/callable_and_then/caller.rb +1 -1
- data/lib/bcdd/result/config/switchers/addons.rb +2 -2
- data/lib/bcdd/result/config/switchers/constant_aliases.rb +1 -3
- data/lib/bcdd/result/config/switchers/features.rb +5 -5
- data/lib/bcdd/result/config/switchers/pattern_matching.rb +1 -1
- data/lib/bcdd/result/config.rb +7 -5
- data/lib/bcdd/result/contract/type_checker.rb +4 -0
- data/lib/bcdd/result/{transitions → event_logs}/config.rb +5 -3
- data/lib/bcdd/result/{transitions → event_logs}/listener.rb +5 -5
- data/lib/bcdd/result/{transitions → event_logs}/listeners.rb +17 -17
- data/lib/bcdd/result/{transitions → event_logs}/tracking/disabled.rb +1 -1
- data/lib/bcdd/result/{transitions → event_logs}/tracking/enabled.rb +15 -13
- data/lib/bcdd/result/{transitions → event_logs}/tracking.rb +4 -3
- data/lib/bcdd/result/{transitions → event_logs}/tree.rb +27 -11
- data/lib/bcdd/result/event_logs.rb +27 -0
- data/lib/bcdd/result/failure.rb +1 -3
- data/lib/bcdd/result/success.rb +1 -3
- data/lib/bcdd/result/version.rb +1 -1
- data/lib/bcdd/result.rb +23 -191
- data/lib/bcdd/success.rb +23 -0
- data/sig/bcdd/context.rbs +175 -0
- data/sig/bcdd/failure.rbs +13 -0
- data/sig/bcdd/result/config.rbs +1 -3
- data/sig/bcdd/result/context.rbs +2 -174
- data/sig/bcdd/result/contract.rbs +1 -0
- data/sig/bcdd/result/{transitions.rbs → event_logs.rbs} +19 -19
- data/sig/bcdd/result.rbs +13 -31
- data/sig/bcdd/success.rbs +13 -0
- metadata +41 -24
- data/examples/multiple_listeners/lib/bcdd/result/transitions_record.rb +0 -28
- data/examples/multiple_listeners/lib/transitions_listener/stdout.rb +0 -54
- data/lib/bcdd/result/context/failure.rb +0 -9
- data/lib/bcdd/result/context.rb +0 -93
- data/lib/bcdd/result/failure/methods.rb +0 -21
- data/lib/bcdd/result/success/methods.rb +0 -21
- data/lib/bcdd/result/transitions.rb +0 -27
data/lib/bcdd/result/config.rb
CHANGED
@@ -9,8 +9,6 @@ require_relative 'config/switchers/pattern_matching'
|
|
9
9
|
|
10
10
|
class BCDD::Result
|
11
11
|
class Config
|
12
|
-
include ::Singleton
|
13
|
-
|
14
12
|
attr_reader :addon, :feature, :constant_alias, :pattern_matching
|
15
13
|
|
16
14
|
def initialize
|
@@ -21,8 +19,8 @@ class BCDD::Result
|
|
21
19
|
@and_then_ = CallableAndThen::Config.new
|
22
20
|
end
|
23
21
|
|
24
|
-
def
|
25
|
-
|
22
|
+
def event_logs
|
23
|
+
EventLogs::Config.instance
|
26
24
|
end
|
27
25
|
|
28
26
|
def and_then!
|
@@ -35,7 +33,7 @@ class BCDD::Result
|
|
35
33
|
constant_alias.freeze
|
36
34
|
pattern_matching.freeze
|
37
35
|
and_then!.freeze
|
38
|
-
|
36
|
+
event_logs.freeze
|
39
37
|
|
40
38
|
super
|
41
39
|
end
|
@@ -58,5 +56,9 @@ class BCDD::Result
|
|
58
56
|
"options=#{options.keys.sort.inspect} " \
|
59
57
|
"and_then!=#{and_then!.options.inspect}>"
|
60
58
|
end
|
59
|
+
|
60
|
+
@instance = new
|
61
|
+
|
62
|
+
singleton_class.send(:attr_reader, :instance)
|
61
63
|
end
|
62
64
|
end
|
@@ -1,9 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module BCDD::Result::
|
3
|
+
module BCDD::Result::EventLogs
|
4
4
|
class Config
|
5
|
-
include ::Singleton
|
6
|
-
|
7
5
|
attr_reader :listener, :trace_id
|
8
6
|
|
9
7
|
def initialize
|
@@ -22,5 +20,9 @@ module BCDD::Result::Transitions
|
|
22
20
|
|
23
21
|
@trace_id = arg
|
24
22
|
end
|
23
|
+
|
24
|
+
@instance = new
|
25
|
+
|
26
|
+
singleton_class.send(:attr_reader, :instance)
|
25
27
|
end
|
26
28
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module BCDD::Result::
|
3
|
+
module BCDD::Result::EventLogs
|
4
4
|
module Listener
|
5
5
|
module ClassMethods
|
6
|
-
def
|
6
|
+
def around_event_logs?
|
7
7
|
false
|
8
8
|
end
|
9
9
|
|
@@ -26,7 +26,7 @@ module BCDD::Result::Transitions
|
|
26
26
|
|
27
27
|
def on_start(scope:); end
|
28
28
|
|
29
|
-
def
|
29
|
+
def around_event_logs(scope:)
|
30
30
|
yield
|
31
31
|
end
|
32
32
|
|
@@ -36,9 +36,9 @@ module BCDD::Result::Transitions
|
|
36
36
|
|
37
37
|
def on_record(record:); end
|
38
38
|
|
39
|
-
def on_finish(
|
39
|
+
def on_finish(event_logs:); end
|
40
40
|
|
41
|
-
def before_interruption(exception:,
|
41
|
+
def before_interruption(exception:, event_logs:); end
|
42
42
|
end
|
43
43
|
|
44
44
|
module Listener::Null
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module BCDD::Result::
|
3
|
+
module BCDD::Result::EventLogs
|
4
4
|
class Listeners
|
5
5
|
class Chain
|
6
6
|
include Listener
|
@@ -13,26 +13,26 @@ module BCDD::Result::Transitions
|
|
13
13
|
end
|
14
14
|
|
15
15
|
around_and_then = list.select(&:around_and_then?)
|
16
|
-
|
16
|
+
around_event_logs = list.select(&:around_event_logs?)
|
17
17
|
|
18
18
|
raise ArgumentError, 'only one listener can have around_and_then? == true' if around_and_then.size > 1
|
19
|
-
raise ArgumentError, 'only one listener can have
|
19
|
+
raise ArgumentError, 'only one listener can have around_event_logs? == true' if around_event_logs.size > 1
|
20
20
|
|
21
|
-
@listeners = { list: list, around_and_then: around_and_then[0],
|
21
|
+
@listeners = { list: list, around_and_then: around_and_then[0], around_event_logs: around_event_logs[0] }
|
22
22
|
end
|
23
23
|
|
24
24
|
def new
|
25
|
-
list, around_and_then,
|
25
|
+
list, around_and_then, around_event_logs = listeners[:list], nil, nil
|
26
26
|
|
27
27
|
instances = list.map do |item|
|
28
28
|
instance = item.new
|
29
29
|
around_and_then = instance if listener?(:around_and_then, instance)
|
30
|
-
|
30
|
+
around_event_logs = instance if listener?(:around_event_logs, instance)
|
31
31
|
|
32
32
|
instance
|
33
33
|
end
|
34
34
|
|
35
|
-
list.one? ? list[0].new : Listeners.send(:new, instances, around_and_then,
|
35
|
+
list.one? ? list[0].new : Listeners.send(:new, instances, around_and_then, around_event_logs)
|
36
36
|
end
|
37
37
|
|
38
38
|
private
|
@@ -50,22 +50,22 @@ module BCDD::Result::Transitions
|
|
50
50
|
Chain.new(listeners)
|
51
51
|
end
|
52
52
|
|
53
|
-
attr_reader :listeners, :around_and_then_listener, :
|
53
|
+
attr_reader :listeners, :around_and_then_listener, :around_event_logs_listener
|
54
54
|
|
55
|
-
private :listeners, :around_and_then_listener, :
|
55
|
+
private :listeners, :around_and_then_listener, :around_event_logs_listener
|
56
56
|
|
57
|
-
def initialize(listeners, around_and_then_listener,
|
57
|
+
def initialize(listeners, around_and_then_listener, around_event_logs_listener)
|
58
58
|
@listeners = listeners
|
59
59
|
@around_and_then_listener = around_and_then_listener || Listener::Null
|
60
|
-
@
|
60
|
+
@around_event_logs_listener = around_event_logs_listener || Listener::Null
|
61
61
|
end
|
62
62
|
|
63
63
|
def on_start(scope:)
|
64
64
|
listeners.each { _1.on_start(scope: scope) }
|
65
65
|
end
|
66
66
|
|
67
|
-
def
|
68
|
-
|
67
|
+
def around_event_logs(scope:, &block)
|
68
|
+
around_event_logs_listener.around_event_logs(scope: scope, &block)
|
69
69
|
end
|
70
70
|
|
71
71
|
def around_and_then(scope:, and_then:, &block)
|
@@ -76,12 +76,12 @@ module BCDD::Result::Transitions
|
|
76
76
|
listeners.each { _1.on_record(record: record) }
|
77
77
|
end
|
78
78
|
|
79
|
-
def on_finish(
|
80
|
-
listeners.each { _1.on_finish(
|
79
|
+
def on_finish(event_logs:)
|
80
|
+
listeners.each { _1.on_finish(event_logs: event_logs) }
|
81
81
|
end
|
82
82
|
|
83
|
-
def before_interruption(exception:,
|
84
|
-
listeners.each { _1.before_interruption(exception: exception,
|
83
|
+
def before_interruption(exception:, event_logs:)
|
84
|
+
listeners.each { _1.before_interruption(exception: exception, event_logs: event_logs) }
|
85
85
|
end
|
86
86
|
end
|
87
87
|
end
|
@@ -1,32 +1,32 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module BCDD::Result::
|
3
|
+
module BCDD::Result::EventLogs
|
4
4
|
class Tracking::Enabled
|
5
5
|
attr_accessor :tree, :records, :root_started_at, :listener
|
6
6
|
|
7
7
|
private :tree, :tree=, :records, :records=, :root_started_at, :root_started_at=, :listener, :listener=
|
8
8
|
|
9
9
|
def exec(name, desc)
|
10
|
-
|
10
|
+
event_log_node, scope = start(name, desc)
|
11
11
|
|
12
12
|
result = nil
|
13
13
|
|
14
|
-
listener.
|
14
|
+
listener.around_event_logs(scope: scope) do
|
15
15
|
result = EnsureResult[yield]
|
16
16
|
end
|
17
17
|
|
18
|
-
tree.move_to_root! if
|
18
|
+
tree.move_to_root! if event_log_node.root?
|
19
19
|
|
20
20
|
finish(result)
|
21
21
|
|
22
22
|
result
|
23
23
|
rescue ::Exception => e
|
24
|
-
err!(e,
|
24
|
+
err!(e, event_log_node)
|
25
25
|
end
|
26
26
|
|
27
|
-
def err!(exception,
|
28
|
-
if
|
29
|
-
listener.before_interruption(exception: exception,
|
27
|
+
def err!(exception, event_log_node)
|
28
|
+
if event_log_node.root?
|
29
|
+
listener.before_interruption(exception: exception, event_logs: map_event_logs)
|
30
30
|
|
31
31
|
reset!
|
32
32
|
end
|
@@ -90,11 +90,11 @@ module BCDD::Result::Transitions
|
|
90
90
|
|
91
91
|
return unless node.root?
|
92
92
|
|
93
|
-
|
93
|
+
event_logs = map_event_logs
|
94
94
|
|
95
|
-
result.send(:
|
95
|
+
result.send(:event_logs=, event_logs)
|
96
96
|
|
97
|
-
listener.on_finish(
|
97
|
+
listener.on_finish(event_logs: event_logs)
|
98
98
|
|
99
99
|
reset!
|
100
100
|
end
|
@@ -136,12 +136,14 @@ module BCDD::Result::Transitions
|
|
136
136
|
::Process.clock_gettime(::Process::CLOCK_MONOTONIC, :millisecond)
|
137
137
|
end
|
138
138
|
|
139
|
-
def
|
139
|
+
def map_event_logs
|
140
140
|
duration = (now_in_milliseconds - root_started_at)
|
141
141
|
|
142
142
|
trace_id = Config.instance.trace_id.call
|
143
143
|
|
144
|
-
|
144
|
+
ids = { tree: tree.ids, matrix: tree.ids_matrix, level_parent: tree.ids_level_parent }
|
145
|
+
|
146
|
+
metadata = { duration: duration, trace_id: trace_id, ids: ids }
|
145
147
|
|
146
148
|
{ version: Tracking::VERSION, records: records, metadata: metadata }
|
147
149
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class BCDD::Result
|
4
|
-
module
|
4
|
+
module EventLogs
|
5
5
|
module Tracking
|
6
6
|
require_relative 'tracking/enabled'
|
7
7
|
require_relative 'tracking/disabled'
|
@@ -11,14 +11,15 @@ class BCDD::Result
|
|
11
11
|
EMPTY_ARRAY = [].freeze
|
12
12
|
EMPTY_HASH = {}.freeze
|
13
13
|
EMPTY_TREE = Tree.new(nil).freeze
|
14
|
+
EMPTY_IDS = { tree: EMPTY_ARRAY, matrix: EMPTY_HASH, level_parent: EMPTY_HASH }.freeze
|
14
15
|
EMPTY = {
|
15
16
|
version: VERSION,
|
16
17
|
records: EMPTY_ARRAY,
|
17
|
-
metadata: { duration: 0,
|
18
|
+
metadata: { duration: 0, ids: EMPTY_IDS, trace_id: nil }.freeze
|
18
19
|
}.freeze
|
19
20
|
|
20
21
|
def self.instance
|
21
|
-
::BCDD::Result::Config.instance.feature.enabled?(:
|
22
|
+
::BCDD::Result::Config.instance.feature.enabled?(:event_logs) ? Tracking::Enabled.new : Tracking::Disabled
|
22
23
|
end
|
23
24
|
end
|
24
25
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class BCDD::Result
|
4
|
-
module
|
4
|
+
module EventLogs
|
5
5
|
class Tree
|
6
6
|
class Node
|
7
7
|
attr_reader :id, :value, :parent, :normalizer, :children
|
@@ -89,13 +89,17 @@ class BCDD::Result
|
|
89
89
|
move_to!(root)
|
90
90
|
end
|
91
91
|
|
92
|
-
|
92
|
+
Ids = ->(node) { [node.id, node.children.map(&Ids)] }
|
93
93
|
|
94
|
-
def
|
95
|
-
|
94
|
+
def ids
|
95
|
+
Ids[root]
|
96
96
|
end
|
97
97
|
|
98
|
-
|
98
|
+
def ids_list
|
99
|
+
ids.flatten
|
100
|
+
end
|
101
|
+
|
102
|
+
IdsMatrix = ->(tree, row, col, memo, previous) do
|
99
103
|
last_row = previous[0]
|
100
104
|
|
101
105
|
tree.each_with_index do |node, index|
|
@@ -103,22 +107,34 @@ class BCDD::Result
|
|
103
107
|
|
104
108
|
id, leaf = node
|
105
109
|
|
106
|
-
|
110
|
+
memo[id] = previous == [row, col] ? [row, col + 1] : [row, col]
|
107
111
|
|
108
|
-
previous =
|
112
|
+
previous = memo[id]
|
109
113
|
|
110
|
-
IdsMatrix[leaf, row, col + 1,
|
114
|
+
IdsMatrix[leaf, row, col + 1, memo, previous]
|
111
115
|
end
|
112
116
|
end
|
113
117
|
|
114
118
|
def ids_matrix
|
115
119
|
current = [0, 0]
|
116
120
|
|
117
|
-
|
121
|
+
memo = { 0 => current }
|
122
|
+
|
123
|
+
IdsMatrix[ids[1], 1, 1, memo, current]
|
124
|
+
|
125
|
+
memo
|
126
|
+
end
|
127
|
+
|
128
|
+
IdsLevelParent = ->((id, node), parent = 0, level = 0, memo = {}) do
|
129
|
+
memo[id] = [level, parent]
|
118
130
|
|
119
|
-
|
131
|
+
node.each { |leaf| IdsLevelParent[leaf, id, level + 1, memo] }
|
132
|
+
|
133
|
+
memo
|
134
|
+
end
|
120
135
|
|
121
|
-
|
136
|
+
def ids_level_parent
|
137
|
+
IdsLevelParent[ids]
|
122
138
|
end
|
123
139
|
end
|
124
140
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result
|
4
|
+
module EventLogs
|
5
|
+
require_relative 'event_logs/listener'
|
6
|
+
require_relative 'event_logs/listeners'
|
7
|
+
require_relative 'event_logs/config'
|
8
|
+
require_relative 'event_logs/tree'
|
9
|
+
require_relative 'event_logs/tracking'
|
10
|
+
|
11
|
+
THREAD_VAR_NAME = :bcdd_result_event_logs_tracking
|
12
|
+
|
13
|
+
EnsureResult = ->(result) do
|
14
|
+
return result if result.is_a?(::BCDD::Result)
|
15
|
+
|
16
|
+
raise Error::UnexpectedOutcome.build(outcome: result, origin: :event_logs)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.tracking
|
20
|
+
Thread.current[THREAD_VAR_NAME] ||= Tracking.instance
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.event_logs(name: nil, desc: nil, &block)
|
25
|
+
EventLogs.tracking.exec(name, desc, &block)
|
26
|
+
end
|
27
|
+
end
|
data/lib/bcdd/result/failure.rb
CHANGED
data/lib/bcdd/result/success.rb
CHANGED
data/lib/bcdd/result/version.rb
CHANGED
data/lib/bcdd/result.rb
CHANGED
@@ -1,197 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'set'
|
4
|
-
require 'singleton'
|
5
4
|
|
6
|
-
|
7
|
-
require_relative '
|
8
|
-
require_relative '
|
9
|
-
|
10
|
-
|
11
|
-
require_relative 'result/
|
12
|
-
require_relative 'result/
|
13
|
-
require_relative 'result/
|
14
|
-
require_relative 'result/
|
15
|
-
require_relative 'result/
|
16
|
-
require_relative 'result/
|
17
|
-
require_relative 'result/
|
18
|
-
require_relative 'result/
|
19
|
-
require_relative 'result/
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
def self.config
|
31
|
-
Config.instance
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.configuration(freeze: true)
|
35
|
-
yield(config)
|
36
|
-
|
37
|
-
freeze and config.freeze
|
38
|
-
end
|
39
|
-
|
40
|
-
def initialize(type:, value:, source: nil, expectations: nil, terminal: nil)
|
41
|
-
data = Data.new(kind, type, value)
|
42
|
-
|
43
|
-
@type_checker = Contract.evaluate(data, expectations)
|
44
|
-
@source = source
|
45
|
-
@terminal = kind == :failure || (terminal && !IgnoredTypes.include?(type))
|
46
|
-
@data = data
|
47
|
-
|
48
|
-
self.unknown = true
|
49
|
-
self.transitions = Transitions::Tracking::EMPTY
|
50
|
-
|
51
|
-
Transitions.tracking.record(self)
|
52
|
-
end
|
53
|
-
|
54
|
-
def terminal?
|
55
|
-
terminal
|
56
|
-
end
|
57
|
-
|
58
|
-
def type
|
59
|
-
data.type
|
60
|
-
end
|
61
|
-
|
62
|
-
def value
|
63
|
-
data.value
|
64
|
-
end
|
65
|
-
|
66
|
-
def success?(_type = nil)
|
67
|
-
raise Error::NotImplemented
|
68
|
-
end
|
69
|
-
|
70
|
-
def failure?(_type = nil)
|
71
|
-
raise Error::NotImplemented
|
72
|
-
end
|
73
|
-
|
74
|
-
def value_or(&_block)
|
75
|
-
raise Error::NotImplemented
|
76
|
-
end
|
77
|
-
|
78
|
-
def on(*types, &block)
|
79
|
-
raise Error::MissingTypeArgument if types.empty?
|
80
|
-
|
81
|
-
tap { known(block) if type_checker.allow?(types) }
|
82
|
-
end
|
83
|
-
|
84
|
-
def on_success(*types, &block)
|
85
|
-
tap { known(block) if type_checker.allow_success?(types) && success? }
|
86
|
-
end
|
87
|
-
|
88
|
-
def on_failure(*types, &block)
|
89
|
-
tap { known(block) if type_checker.allow_failure?(types) && failure? }
|
90
|
-
end
|
91
|
-
|
92
|
-
def on_unknown
|
93
|
-
tap { yield(value, type) if unknown }
|
94
|
-
end
|
95
|
-
|
96
|
-
def and_then(method_name = nil, injected_value = nil, &block)
|
97
|
-
return self if terminal?
|
98
|
-
|
99
|
-
method_name && block and raise ::ArgumentError, 'method_name and block are mutually exclusive'
|
100
|
-
|
101
|
-
method_name ? call_and_then_source_method(method_name, injected_value) : call_and_then_block(block)
|
102
|
-
end
|
103
|
-
|
104
|
-
def and_then!(source, injected_value = nil, _call: nil)
|
105
|
-
raise Error::CallableAndThenDisabled unless Config.instance.feature.enabled?(:and_then!)
|
106
|
-
|
107
|
-
return self if terminal?
|
108
|
-
|
109
|
-
call_and_then_callable!(source, value: value, injected_value: injected_value, method_name: _call)
|
110
|
-
end
|
111
|
-
|
112
|
-
def handle
|
113
|
-
handler = Handler.new(self, type_checker: type_checker)
|
114
|
-
|
115
|
-
yield handler
|
116
|
-
|
117
|
-
handler.send(:outcome)
|
118
|
-
end
|
119
|
-
|
120
|
-
def ==(other)
|
121
|
-
self.class == other.class && type == other.type && value == other.value
|
122
|
-
end
|
123
|
-
|
124
|
-
def hash
|
125
|
-
[self.class, type, value].hash
|
126
|
-
end
|
127
|
-
|
128
|
-
def inspect
|
129
|
-
format('#<%<class_name>s type=%<type>p value=%<value>p>', class_name: self.class.name, type: type, value: value)
|
130
|
-
end
|
131
|
-
|
132
|
-
def deconstruct
|
133
|
-
[type, value]
|
134
|
-
end
|
135
|
-
|
136
|
-
def deconstruct_keys(_keys)
|
137
|
-
{ kind => { type => value } }
|
138
|
-
end
|
139
|
-
|
140
|
-
alias eql? ==
|
141
|
-
alias on_type on
|
142
|
-
|
143
|
-
private
|
144
|
-
|
145
|
-
def kind
|
146
|
-
:unknown
|
147
|
-
end
|
148
|
-
|
149
|
-
def known(block)
|
150
|
-
self.unknown = false
|
151
|
-
|
152
|
-
block.call(value, type)
|
153
|
-
end
|
154
|
-
|
155
|
-
def call_and_then_source_method(method_name, injected_value)
|
156
|
-
method = source.method(method_name)
|
157
|
-
|
158
|
-
Transitions.tracking.record_and_then(method, injected_value) do
|
159
|
-
result = call_and_then_source_method!(method, injected_value)
|
160
|
-
|
161
|
-
ensure_result_object(result, origin: :method)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
def call_and_then_source_method!(method, injected_value)
|
166
|
-
case method.arity
|
167
|
-
when 0 then source.send(method.name)
|
168
|
-
when 1 then source.send(method.name, value)
|
169
|
-
when 2 then source.send(method.name, value, injected_value)
|
170
|
-
else raise Error::InvalidSourceMethodArity.build(source: source, method: method, max_arity: 2)
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
def call_and_then_block(block)
|
175
|
-
Transitions.tracking.record_and_then(:block, nil) do
|
176
|
-
result = call_and_then_block!(block)
|
177
|
-
|
178
|
-
ensure_result_object(result, origin: :block)
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
def call_and_then_block!(block)
|
183
|
-
block.call(value)
|
184
|
-
end
|
185
|
-
|
186
|
-
def call_and_then_callable!(source, value:, injected_value:, method_name:)
|
187
|
-
CallableAndThen::Caller.call(source, value: value, injected_value: injected_value, method_name: method_name)
|
188
|
-
end
|
189
|
-
|
190
|
-
def ensure_result_object(result, origin:)
|
191
|
-
raise Error::UnexpectedOutcome.build(outcome: result, origin: origin) unless result.is_a?(::BCDD::Result)
|
192
|
-
|
193
|
-
return result if result.source.equal?(source)
|
194
|
-
|
195
|
-
raise Error::InvalidResultSource.build(given_result: result, expected_source: source)
|
5
|
+
module BCDD
|
6
|
+
require_relative 'success'
|
7
|
+
require_relative 'failure'
|
8
|
+
|
9
|
+
class Result
|
10
|
+
require_relative 'result/version'
|
11
|
+
require_relative 'result/error'
|
12
|
+
require_relative 'result/ignored_types'
|
13
|
+
require_relative 'result/event_logs'
|
14
|
+
require_relative 'result/callable_and_then'
|
15
|
+
require_relative 'result/data'
|
16
|
+
require_relative 'result/handler'
|
17
|
+
require_relative 'result/failure'
|
18
|
+
require_relative 'result/success'
|
19
|
+
require_relative 'result/mixin'
|
20
|
+
require_relative 'result/contract'
|
21
|
+
require_relative 'result/expectations'
|
22
|
+
require_relative 'result/config'
|
23
|
+
require_relative 'result/_self'
|
24
|
+
|
25
|
+
require_relative 'context'
|
26
|
+
|
27
|
+
Context = ::BCDD::Context
|
196
28
|
end
|
197
29
|
end
|
data/lib/bcdd/success.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BCDD
|
4
|
+
module Success
|
5
|
+
def success?(type = nil)
|
6
|
+
type.nil? || type_checker.allow_success?([type])
|
7
|
+
end
|
8
|
+
|
9
|
+
def failure?(_type = nil)
|
10
|
+
false
|
11
|
+
end
|
12
|
+
|
13
|
+
def value_or
|
14
|
+
value
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def kind
|
20
|
+
:success
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|