bcdd-result 0.13.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -4
  3. data/CHANGELOG.md +46 -17
  4. data/README.md +381 -220
  5. data/Rakefile +1 -1
  6. data/Steepfile +1 -1
  7. data/examples/multiple_listeners/Rakefile +8 -8
  8. data/examples/multiple_listeners/app/models/account/owner_creation.rb +1 -1
  9. data/examples/multiple_listeners/app/models/user/creation.rb +1 -1
  10. data/examples/multiple_listeners/app/models/user/token/creation.rb +1 -1
  11. data/examples/multiple_listeners/config/initializers/bcdd.rb +0 -2
  12. data/examples/multiple_listeners/config.rb +3 -3
  13. data/examples/multiple_listeners/db/setup.rb +2 -3
  14. data/examples/multiple_listeners/lib/bcdd/result/event_logs_record.rb +27 -0
  15. data/examples/multiple_listeners/lib/event_logs_listener/stdout.rb +60 -0
  16. data/examples/multiple_listeners/lib/runtime_breaker.rb +1 -1
  17. data/examples/service_objects/Rakefile +36 -0
  18. data/examples/service_objects/app/models/account/member.rb +10 -0
  19. data/examples/service_objects/app/models/account.rb +11 -0
  20. data/examples/service_objects/app/models/user/token.rb +7 -0
  21. data/examples/service_objects/app/models/user.rb +15 -0
  22. data/examples/service_objects/app/services/account/owner_creation.rb +47 -0
  23. data/examples/service_objects/app/services/application_service.rb +79 -0
  24. data/examples/service_objects/app/services/user/creation.rb +56 -0
  25. data/examples/service_objects/app/services/user/token/creation.rb +37 -0
  26. data/examples/service_objects/config/boot.rb +17 -0
  27. data/examples/service_objects/config/initializers/bcdd.rb +9 -0
  28. data/examples/service_objects/config.rb +20 -0
  29. data/examples/service_objects/db/setup.rb +49 -0
  30. data/examples/single_listener/Rakefile +5 -5
  31. data/examples/single_listener/app/models/account/owner_creation.rb +1 -1
  32. data/examples/single_listener/app/models/user/creation.rb +1 -1
  33. data/examples/single_listener/app/models/user/token/creation.rb +1 -1
  34. data/examples/single_listener/config/initializers/bcdd.rb +0 -2
  35. data/examples/single_listener/config.rb +1 -1
  36. data/examples/single_listener/lib/{single_transitions_listener.rb → single_event_logs_listener.rb} +32 -23
  37. data/lib/bcdd/{result/context → context}/callable_and_then.rb +5 -4
  38. data/lib/bcdd/{result/context → context}/expectations/mixin.rb +1 -1
  39. data/lib/bcdd/{result/context → context}/expectations.rb +2 -2
  40. data/lib/bcdd/context/failure.rb +9 -0
  41. data/lib/bcdd/{result/context → context}/mixin.rb +2 -2
  42. data/lib/bcdd/{result/context → context}/success.rb +6 -6
  43. data/lib/bcdd/context.rb +91 -0
  44. data/lib/bcdd/failure.rb +23 -0
  45. data/lib/bcdd/result/_self.rb +198 -0
  46. data/lib/bcdd/result/callable_and_then/caller.rb +1 -1
  47. data/lib/bcdd/result/config/switchers/addons.rb +2 -2
  48. data/lib/bcdd/result/config/switchers/constant_aliases.rb +1 -3
  49. data/lib/bcdd/result/config/switchers/features.rb +5 -5
  50. data/lib/bcdd/result/config/switchers/pattern_matching.rb +1 -1
  51. data/lib/bcdd/result/config.rb +7 -5
  52. data/lib/bcdd/result/contract/type_checker.rb +4 -0
  53. data/lib/bcdd/result/{transitions → event_logs}/config.rb +5 -3
  54. data/lib/bcdd/result/{transitions → event_logs}/listener.rb +5 -5
  55. data/lib/bcdd/result/{transitions → event_logs}/listeners.rb +17 -17
  56. data/lib/bcdd/result/{transitions → event_logs}/tracking/disabled.rb +1 -1
  57. data/lib/bcdd/result/{transitions → event_logs}/tracking/enabled.rb +15 -13
  58. data/lib/bcdd/result/{transitions → event_logs}/tracking.rb +4 -3
  59. data/lib/bcdd/result/{transitions → event_logs}/tree.rb +27 -11
  60. data/lib/bcdd/result/event_logs.rb +27 -0
  61. data/lib/bcdd/result/failure.rb +1 -3
  62. data/lib/bcdd/result/success.rb +1 -3
  63. data/lib/bcdd/result/version.rb +1 -1
  64. data/lib/bcdd/result.rb +23 -191
  65. data/lib/bcdd/success.rb +23 -0
  66. data/sig/bcdd/context.rbs +175 -0
  67. data/sig/bcdd/failure.rbs +13 -0
  68. data/sig/bcdd/result/config.rbs +1 -3
  69. data/sig/bcdd/result/context.rbs +2 -174
  70. data/sig/bcdd/result/contract.rbs +1 -0
  71. data/sig/bcdd/result/{transitions.rbs → event_logs.rbs} +19 -19
  72. data/sig/bcdd/result.rbs +13 -31
  73. data/sig/bcdd/success.rbs +13 -0
  74. metadata +41 -24
  75. data/examples/multiple_listeners/lib/bcdd/result/transitions_record.rb +0 -28
  76. data/examples/multiple_listeners/lib/transitions_listener/stdout.rb +0 -54
  77. data/lib/bcdd/result/context/failure.rb +0 -9
  78. data/lib/bcdd/result/context.rb +0 -93
  79. data/lib/bcdd/result/failure/methods.rb +0 -21
  80. data/lib/bcdd/result/success/methods.rb +0 -21
  81. data/lib/bcdd/result/transitions.rb +0 -27
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bcdd-result
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rodrigo Serradura
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-02-01 00:00:00.000000000 Z
11
+ date: 2024-03-16 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Unleash a pragmatic and observable use of Result Pattern and Railway-Oriented
14
14
  Programming in Ruby.
@@ -38,10 +38,23 @@ files:
38
38
  - examples/multiple_listeners/config/boot.rb
39
39
  - examples/multiple_listeners/config/initializers/bcdd.rb
40
40
  - examples/multiple_listeners/db/setup.rb
41
+ - examples/multiple_listeners/lib/bcdd/result/event_logs_record.rb
41
42
  - examples/multiple_listeners/lib/bcdd/result/rollback_on_failure.rb
42
- - examples/multiple_listeners/lib/bcdd/result/transitions_record.rb
43
+ - examples/multiple_listeners/lib/event_logs_listener/stdout.rb
43
44
  - examples/multiple_listeners/lib/runtime_breaker.rb
44
- - examples/multiple_listeners/lib/transitions_listener/stdout.rb
45
+ - examples/service_objects/Rakefile
46
+ - examples/service_objects/app/models/account.rb
47
+ - examples/service_objects/app/models/account/member.rb
48
+ - examples/service_objects/app/models/user.rb
49
+ - examples/service_objects/app/models/user/token.rb
50
+ - examples/service_objects/app/services/account/owner_creation.rb
51
+ - examples/service_objects/app/services/application_service.rb
52
+ - examples/service_objects/app/services/user/creation.rb
53
+ - examples/service_objects/app/services/user/token/creation.rb
54
+ - examples/service_objects/config.rb
55
+ - examples/service_objects/config/boot.rb
56
+ - examples/service_objects/config/initializers/bcdd.rb
57
+ - examples/service_objects/db/setup.rb
45
58
  - examples/single_listener/Rakefile
46
59
  - examples/single_listener/app/models/account.rb
47
60
  - examples/single_listener/app/models/account/member.rb
@@ -56,9 +69,18 @@ files:
56
69
  - examples/single_listener/db/setup.rb
57
70
  - examples/single_listener/lib/bcdd/result/rollback_on_failure.rb
58
71
  - examples/single_listener/lib/runtime_breaker.rb
59
- - examples/single_listener/lib/single_transitions_listener.rb
72
+ - examples/single_listener/lib/single_event_logs_listener.rb
60
73
  - lib/bcdd-result.rb
74
+ - lib/bcdd/context.rb
75
+ - lib/bcdd/context/callable_and_then.rb
76
+ - lib/bcdd/context/expectations.rb
77
+ - lib/bcdd/context/expectations/mixin.rb
78
+ - lib/bcdd/context/failure.rb
79
+ - lib/bcdd/context/mixin.rb
80
+ - lib/bcdd/context/success.rb
81
+ - lib/bcdd/failure.rb
61
82
  - lib/bcdd/result.rb
83
+ - lib/bcdd/result/_self.rb
62
84
  - lib/bcdd/result/callable_and_then.rb
63
85
  - lib/bcdd/result/callable_and_then/caller.rb
64
86
  - lib/bcdd/result/callable_and_then/config.rb
@@ -70,13 +92,6 @@ files:
70
92
  - lib/bcdd/result/config/switchers/constant_aliases.rb
71
93
  - lib/bcdd/result/config/switchers/features.rb
72
94
  - lib/bcdd/result/config/switchers/pattern_matching.rb
73
- - lib/bcdd/result/context.rb
74
- - lib/bcdd/result/context/callable_and_then.rb
75
- - lib/bcdd/result/context/expectations.rb
76
- - lib/bcdd/result/context/expectations/mixin.rb
77
- - lib/bcdd/result/context/failure.rb
78
- - lib/bcdd/result/context/mixin.rb
79
- - lib/bcdd/result/context/success.rb
80
95
  - lib/bcdd/result/contract.rb
81
96
  - lib/bcdd/result/contract/disabled.rb
82
97
  - lib/bcdd/result/contract/error.rb
@@ -87,25 +102,26 @@ files:
87
102
  - lib/bcdd/result/contract/type_checker.rb
88
103
  - lib/bcdd/result/data.rb
89
104
  - lib/bcdd/result/error.rb
105
+ - lib/bcdd/result/event_logs.rb
106
+ - lib/bcdd/result/event_logs/config.rb
107
+ - lib/bcdd/result/event_logs/listener.rb
108
+ - lib/bcdd/result/event_logs/listeners.rb
109
+ - lib/bcdd/result/event_logs/tracking.rb
110
+ - lib/bcdd/result/event_logs/tracking/disabled.rb
111
+ - lib/bcdd/result/event_logs/tracking/enabled.rb
112
+ - lib/bcdd/result/event_logs/tree.rb
90
113
  - lib/bcdd/result/expectations.rb
91
114
  - lib/bcdd/result/expectations/mixin.rb
92
115
  - lib/bcdd/result/failure.rb
93
- - lib/bcdd/result/failure/methods.rb
94
116
  - lib/bcdd/result/handler.rb
95
117
  - lib/bcdd/result/handler/allowed_types.rb
96
118
  - lib/bcdd/result/ignored_types.rb
97
119
  - lib/bcdd/result/mixin.rb
98
120
  - lib/bcdd/result/success.rb
99
- - lib/bcdd/result/success/methods.rb
100
- - lib/bcdd/result/transitions.rb
101
- - lib/bcdd/result/transitions/config.rb
102
- - lib/bcdd/result/transitions/listener.rb
103
- - lib/bcdd/result/transitions/listeners.rb
104
- - lib/bcdd/result/transitions/tracking.rb
105
- - lib/bcdd/result/transitions/tracking/disabled.rb
106
- - lib/bcdd/result/transitions/tracking/enabled.rb
107
- - lib/bcdd/result/transitions/tree.rb
108
121
  - lib/bcdd/result/version.rb
122
+ - lib/bcdd/success.rb
123
+ - sig/bcdd/context.rbs
124
+ - sig/bcdd/failure.rbs
109
125
  - sig/bcdd/result.rbs
110
126
  - sig/bcdd/result/callable_and_then.rbs
111
127
  - sig/bcdd/result/config.rbs
@@ -113,12 +129,13 @@ files:
113
129
  - sig/bcdd/result/contract.rbs
114
130
  - sig/bcdd/result/data.rbs
115
131
  - sig/bcdd/result/error.rbs
132
+ - sig/bcdd/result/event_logs.rbs
116
133
  - sig/bcdd/result/expectations.rbs
117
134
  - sig/bcdd/result/handler.rbs
118
135
  - sig/bcdd/result/ignored_types.rbs
119
136
  - sig/bcdd/result/mixin.rbs
120
- - sig/bcdd/result/transitions.rbs
121
137
  - sig/bcdd/result/version.rbs
138
+ - sig/bcdd/success.rbs
122
139
  homepage: https://github.com/b-cdd/result
123
140
  licenses:
124
141
  - MIT
@@ -143,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
143
160
  - !ruby/object:Gem::Version
144
161
  version: '0'
145
162
  requirements: []
146
- rubygems_version: 3.5.3
163
+ rubygems_version: 3.5.6
147
164
  signing_key:
148
165
  specification_version: 4
149
166
  summary: Unleash a pragmatic and observable use of Result Pattern and Railway-Oriented
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class BCDD::Result::TransitionsRecord < ActiveRecord::Base
4
- self.table_name = 'bcdd_result_transitions'
5
-
6
- class Listener
7
- include ::BCDD::Result::Transitions::Listener
8
-
9
- def on_finish(transitions:)
10
- metadata = transitions[:metadata]
11
- root_name = transitions.dig(:records, 0, :root, :name) || 'Unknown'
12
-
13
- BCDD::Result::TransitionsRecord.create(
14
- root_name: root_name,
15
- trace_id: metadata[:trace_id],
16
- version: transitions[:version],
17
- duration: metadata[:duration],
18
- ids_tree: metadata[:ids_tree],
19
- ids_matrix: metadata[:ids_matrix],
20
- records: transitions[:records]
21
- )
22
- rescue ::StandardError => e
23
- err = "#{e.message} (#{e.class}); Backtrace: #{e.backtrace.join(', ')}"
24
-
25
- ::Kernel.warn "Error on BCDD::Result::TransitionsRecord::Listener#on_finish: #{err}"
26
- end
27
- end
28
- end
@@ -1,54 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class TransitionsListener::Stdout
4
- include BCDD::Result::Transitions::Listener
5
-
6
- def initialize
7
- @buffer = []
8
- end
9
-
10
- def on_start(scope:)
11
- scope => { id:, name:, desc: }
12
-
13
- @buffer << [id, "##{id} #{name} - #{desc}".chomp('- ')]
14
- end
15
-
16
- def on_record(record:)
17
- record => { current: { id: }, result: { kind:, type: } }
18
-
19
- method_name = record.dig(:and_then, :method_name)
20
-
21
- @buffer << [id, " * #{kind}(#{type}) from method: #{method_name}".chomp('from method: ')]
22
- end
23
-
24
- MapNestedMessages = ->(transitions, buffer, hide_given_and_continue) do
25
- ids_matrix = transitions.dig(:metadata, :ids_matrix)
26
-
27
- messages = buffer.filter_map { |(id, msg)| "#{' ' * ids_matrix[id].last}#{msg}" if ids_matrix[id] }
28
-
29
- messages.reject! { _1.match?(/\(_(given|continue)_\)/) } if hide_given_and_continue
30
-
31
- messages
32
- end
33
-
34
- def on_finish(transitions:)
35
- messages = MapNestedMessages[transitions, @buffer, ENV['HIDE_GIVEN_AND_CONTINUE']]
36
-
37
- puts messages.join("\n")
38
- end
39
-
40
- def before_interruption(exception:, transitions:)
41
- messages = MapNestedMessages[transitions, @buffer, ENV['HIDE_GIVEN_AND_CONTINUE']]
42
-
43
- puts messages.join("\n")
44
-
45
- bc = ::ActiveSupport::BacktraceCleaner.new
46
- bc.add_filter { |line| line.gsub(__dir__.sub('/lib', ''), '').sub(/\A\//, '')}
47
- bc.add_silencer { |line| /lib\/bcdd\/result/.match?(line) }
48
- bc.add_silencer { |line| line.include?(RUBY_VERSION) }
49
-
50
- backtrace = bc.clean(exception.backtrace)
51
-
52
- puts "\nException: #{exception.message} (#{exception.class}); Backtrace: #{backtrace.join(", ")}"
53
- end
54
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class BCDD::Result::Context::Failure < BCDD::Result::Context
4
- include BCDD::Result::Failure::Methods
5
-
6
- def and_expose(_type, _keys, **_options)
7
- self
8
- end
9
- end
@@ -1,93 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class BCDD::Result
4
- class Context < self
5
- require_relative 'context/failure'
6
- require_relative 'context/success'
7
- require_relative 'context/mixin'
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'
12
-
13
- def self.Success(type, **value)
14
- Success.new(type: type, value: value)
15
- end
16
-
17
- def self.Failure(type, **value)
18
- Failure.new(type: type, value: value)
19
- end
20
-
21
- def initialize(type:, value:, source: nil, expectations: nil, terminal: nil)
22
- value.is_a?(::Hash) or raise ::ArgumentError, 'value must be a Hash'
23
-
24
- @acc = {}
25
-
26
- super
27
- end
28
-
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)
39
- end
40
-
41
- protected
42
-
43
- attr_reader :acc
44
-
45
- private
46
-
47
- SourceMethodArity = ->(method) do
48
- return 0 if method.arity.zero?
49
-
50
- parameters = method.parameters.map(&:first)
51
-
52
- return 1 if !parameters.empty? && parameters.all?(/\Akey/)
53
-
54
- -1
55
- end
56
-
57
- def call_and_then_source_method!(method, injected_value)
58
- acc.merge!(value.merge(injected_value))
59
-
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)
64
- end
65
- end
66
-
67
- def call_and_then_block!(block)
68
- acc.merge!(value)
69
-
70
- block.call(acc)
71
- end
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
-
79
- def ensure_result_object(result, origin:)
80
- raise_unexpected_outcome_error(result, origin) unless result.is_a?(Context)
81
-
82
- return result.tap { _1.acc.merge!(acc) } if result.source.equal?(source)
83
-
84
- raise Error::InvalidResultSource.build(given_result: result, expected_source: source)
85
- end
86
-
87
- def raise_unexpected_outcome_error(result, origin)
88
- raise Error::UnexpectedOutcome.build(outcome: result, origin: origin, expected: EXPECTED_OUTCOME)
89
- end
90
-
91
- private_constant :SourceMethodArity
92
- end
93
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module BCDD::Result::Failure::Methods
4
- def success?(_type = nil)
5
- false
6
- end
7
-
8
- def failure?(type = nil)
9
- type.nil? || type_checker.allow_failure?([type])
10
- end
11
-
12
- def value_or
13
- yield(value)
14
- end
15
-
16
- private
17
-
18
- def kind
19
- :failure
20
- end
21
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module BCDD::Result::Success::Methods
4
- def success?(type = nil)
5
- type.nil? || type_checker.allow_success?([type])
6
- end
7
-
8
- def failure?(_type = nil)
9
- false
10
- end
11
-
12
- def value_or
13
- value
14
- end
15
-
16
- private
17
-
18
- def kind
19
- :success
20
- end
21
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class BCDD::Result
4
- module Transitions
5
- require_relative 'transitions/listener'
6
- require_relative 'transitions/listeners'
7
- require_relative 'transitions/config'
8
- require_relative 'transitions/tree'
9
- require_relative 'transitions/tracking'
10
-
11
- THREAD_VAR_NAME = :bcdd_result_transitions_tracking
12
-
13
- EnsureResult = ->(result) do
14
- return result if result.is_a?(::BCDD::Result)
15
-
16
- raise Error::UnexpectedOutcome.build(outcome: result, origin: :transitions)
17
- end
18
-
19
- def self.tracking
20
- Thread.current[THREAD_VAR_NAME] ||= Tracking.instance
21
- end
22
- end
23
-
24
- def self.transitions(name: nil, desc: nil, &block)
25
- Transitions.tracking.exec(name, desc, &block)
26
- end
27
- end