bcdd-result 0.12.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +17 -2
  3. data/CHANGELOG.md +99 -16
  4. data/README.md +618 -247
  5. data/Rakefile +1 -1
  6. data/Steepfile +4 -4
  7. data/examples/multiple_listeners/Rakefile +55 -0
  8. data/examples/multiple_listeners/app/models/account/member.rb +10 -0
  9. data/examples/multiple_listeners/app/models/account/owner_creation.rb +62 -0
  10. data/examples/multiple_listeners/app/models/account.rb +11 -0
  11. data/examples/multiple_listeners/app/models/user/creation.rb +67 -0
  12. data/examples/multiple_listeners/app/models/user/token/creation.rb +51 -0
  13. data/examples/multiple_listeners/app/models/user/token.rb +7 -0
  14. data/examples/multiple_listeners/app/models/user.rb +15 -0
  15. data/examples/multiple_listeners/config/boot.rb +16 -0
  16. data/examples/multiple_listeners/config/initializers/bcdd.rb +9 -0
  17. data/examples/multiple_listeners/config.rb +27 -0
  18. data/examples/multiple_listeners/db/setup.rb +60 -0
  19. data/examples/multiple_listeners/lib/bcdd/result/event_logs_record.rb +27 -0
  20. data/examples/multiple_listeners/lib/bcdd/result/rollback_on_failure.rb +15 -0
  21. data/examples/multiple_listeners/lib/event_logs_listener/stdout.rb +60 -0
  22. data/examples/multiple_listeners/lib/runtime_breaker.rb +11 -0
  23. data/examples/service_objects/Rakefile +36 -0
  24. data/examples/service_objects/app/models/account/member.rb +10 -0
  25. data/examples/service_objects/app/models/account.rb +11 -0
  26. data/examples/service_objects/app/models/user/token.rb +7 -0
  27. data/examples/service_objects/app/models/user.rb +15 -0
  28. data/examples/service_objects/app/services/account/owner_creation.rb +47 -0
  29. data/examples/service_objects/app/services/application_service.rb +79 -0
  30. data/examples/service_objects/app/services/user/creation.rb +56 -0
  31. data/examples/service_objects/app/services/user/token/creation.rb +37 -0
  32. data/examples/service_objects/config/boot.rb +17 -0
  33. data/examples/service_objects/config/initializers/bcdd.rb +9 -0
  34. data/examples/service_objects/config.rb +20 -0
  35. data/examples/service_objects/db/setup.rb +49 -0
  36. data/examples/single_listener/Rakefile +92 -0
  37. data/examples/single_listener/app/models/account/member.rb +10 -0
  38. data/examples/single_listener/app/models/account/owner_creation.rb +62 -0
  39. data/examples/single_listener/app/models/account.rb +11 -0
  40. data/examples/single_listener/app/models/user/creation.rb +67 -0
  41. data/examples/single_listener/app/models/user/token/creation.rb +51 -0
  42. data/examples/single_listener/app/models/user/token.rb +7 -0
  43. data/examples/single_listener/app/models/user.rb +15 -0
  44. data/examples/single_listener/config/boot.rb +16 -0
  45. data/examples/single_listener/config/initializers/bcdd.rb +9 -0
  46. data/examples/single_listener/config.rb +23 -0
  47. data/examples/single_listener/db/setup.rb +49 -0
  48. data/examples/single_listener/lib/bcdd/result/rollback_on_failure.rb +15 -0
  49. data/examples/single_listener/lib/runtime_breaker.rb +11 -0
  50. data/examples/single_listener/lib/single_event_logs_listener.rb +117 -0
  51. data/lib/bcdd/{result/context → context}/callable_and_then.rb +5 -4
  52. data/lib/bcdd/{result/context → context}/expectations/mixin.rb +3 -3
  53. data/lib/bcdd/{result/context → context}/expectations.rb +2 -2
  54. data/lib/bcdd/context/failure.rb +9 -0
  55. data/lib/bcdd/{result/context → context}/mixin.rb +4 -4
  56. data/lib/bcdd/context/success.rb +37 -0
  57. data/lib/bcdd/context.rb +91 -0
  58. data/lib/bcdd/failure.rb +23 -0
  59. data/lib/bcdd/result/_self.rb +198 -0
  60. data/lib/bcdd/result/callable_and_then/caller.rb +1 -1
  61. data/lib/bcdd/result/config/switchers/addons.rb +2 -2
  62. data/lib/bcdd/result/config/switchers/constant_aliases.rb +1 -3
  63. data/lib/bcdd/result/config/switchers/features.rb +5 -5
  64. data/lib/bcdd/result/config/switchers/pattern_matching.rb +1 -1
  65. data/lib/bcdd/result/config.rb +9 -2
  66. data/lib/bcdd/result/contract/for_types.rb +1 -1
  67. data/lib/bcdd/result/contract/for_types_and_values.rb +2 -0
  68. data/lib/bcdd/result/contract/type_checker.rb +4 -0
  69. data/lib/bcdd/result/event_logs/config.rb +28 -0
  70. data/lib/bcdd/result/event_logs/listener.rb +51 -0
  71. data/lib/bcdd/result/event_logs/listeners.rb +87 -0
  72. data/lib/bcdd/result/event_logs/tracking/disabled.rb +15 -0
  73. data/lib/bcdd/result/event_logs/tracking/enabled.rb +161 -0
  74. data/lib/bcdd/result/event_logs/tracking.rb +26 -0
  75. data/lib/bcdd/result/{transitions → event_logs}/tree.rb +46 -4
  76. data/lib/bcdd/result/event_logs.rb +27 -0
  77. data/lib/bcdd/result/expectations/mixin.rb +2 -2
  78. data/lib/bcdd/result/failure.rb +1 -3
  79. data/lib/bcdd/result/ignored_types.rb +14 -0
  80. data/lib/bcdd/result/mixin.rb +2 -2
  81. data/lib/bcdd/result/success.rb +1 -3
  82. data/lib/bcdd/result/version.rb +1 -1
  83. data/lib/bcdd/result.rb +25 -191
  84. data/lib/bcdd/success.rb +23 -0
  85. data/sig/bcdd/context.rbs +175 -0
  86. data/sig/bcdd/failure.rbs +13 -0
  87. data/sig/bcdd/result/config.rbs +1 -2
  88. data/sig/bcdd/result/context.rbs +2 -165
  89. data/sig/bcdd/result/contract.rbs +1 -0
  90. data/sig/bcdd/result/event_logs.rbs +189 -0
  91. data/sig/bcdd/result/ignored_types.rbs +9 -0
  92. data/sig/bcdd/result.rbs +14 -32
  93. data/sig/bcdd/success.rbs +13 -0
  94. metadata +75 -22
  95. data/lib/bcdd/result/context/failure.rb +0 -9
  96. data/lib/bcdd/result/context/success.rb +0 -19
  97. data/lib/bcdd/result/context.rb +0 -93
  98. data/lib/bcdd/result/failure/methods.rb +0 -21
  99. data/lib/bcdd/result/success/methods.rb +0 -21
  100. data/lib/bcdd/result/transitions/tracking/disabled.rb +0 -27
  101. data/lib/bcdd/result/transitions/tracking/enabled.rb +0 -100
  102. data/lib/bcdd/result/transitions/tracking.rb +0 -20
  103. data/lib/bcdd/result/transitions.rb +0 -28
  104. data/sig/bcdd/result/transitions.rbs +0 -100
data/README.md CHANGED
@@ -1,9 +1,11 @@
1
1
  <p align="center">
2
2
  <h1 align="center" id="-bcddresult">🔀 BCDD::Result</h1>
3
- <p align="center"><i>Empower Ruby apps with pragmatic use of Result pattern (monad), Railway Oriented Programming, and B/CDD.</i></p>
3
+ <p align="center"><i>Unleash a pragmatic and observable use of Result Pattern and Railway-Oriented Programming in Ruby.</i></p>
4
4
  <p align="center">
5
- <img src="https://img.shields.io/badge/ruby->%3D%202.7.0-ruby.svg?colorA=99004d&colorB=cc0066" alt="Ruby">
5
+ <img src="https://img.shields.io/badge/Ruby%20%3E%3D%202.7%2C%20%3C%3D%20Head-ruby.svg?colorA=444&colorB=333" alt="Ruby">
6
6
  <a href="https://rubygems.org/gems/bcdd-result"><img src="https://badge.fury.io/rb/bcdd-result.svg" alt="bcdd-result gem version" height="18"></a>
7
+ <a href="https://codeclimate.com/github/B-CDD/result/maintainability"><img src="https://api.codeclimate.com/v1/badges/aa8360f8f012d7dedd62/maintainability" /></a>
8
+ <a href="https://codeclimate.com/github/B-CDD/result/test_coverage"><img src="https://api.codeclimate.com/v1/badges/aa8360f8f012d7dedd62/test_coverage" /></a>
7
9
  </p>
8
10
  </p>
9
11
 
@@ -17,12 +19,13 @@ Furthermore, this abstraction exposes several features that will be useful to ma
17
19
 
18
20
  Use it to enable the [Railway Oriented Programming](https://fsharpforfunandprofit.com/rop/) pattern (superpower) in your code.
19
21
 
20
- - [Ruby Version](#ruby-version)
22
+ - [Supported Ruby](#supported-ruby)
21
23
  - [Installation](#installation)
22
24
  - [Usage](#usage)
23
25
  - [`BCDD::Result` *versus* `Result`](#bcddresult-versus-result)
24
26
  - [Reference](#reference)
25
- - [Result Attributes](#result-attributes)
27
+ - [Basic methods](#basic-methods)
28
+ - [Checking types with `result.is?` or `method missing`](#checking-types-with-resultis-or-method-missing)
26
29
  - [Checking types with `result.success?` or `result.failure?`](#checking-types-with-resultsuccess-or-resultfailure)
27
30
  - [Result Hooks](#result-hooks)
28
31
  - [`result.on`](#resulton)
@@ -35,9 +38,6 @@ Use it to enable the [Railway Oriented Programming](https://fsharpforfunandprofi
35
38
  - [`result.value_or`](#resultvalue_or)
36
39
  - [Result Data](#result-data)
37
40
  - [`result.data`](#resultdata)
38
- - [Pattern Matching](#pattern-matching)
39
- - [`Array`/`Find` patterns](#arrayfind-patterns)
40
- - [`Hash` patterns](#hash-patterns)
41
41
  - [Railway Oriented Programming](#railway-oriented-programming)
42
42
  - [`result.and_then`](#resultand_then)
43
43
  - [`BCDD::Result.mixin`](#bcddresultmixin)
@@ -61,22 +61,31 @@ Use it to enable the [Railway Oriented Programming](https://fsharpforfunandprofi
61
61
  - [Failure()](#failure)
62
62
  - [Pattern Matching Support](#pattern-matching-support)
63
63
  - [`BCDD::Result::Expectations.mixin` add-ons](#bcddresultexpectationsmixin-add-ons)
64
- - [`BCDD::Result::Context`](#bcddresultcontext)
64
+ - [`BCDD::Context`](#bcddcontext)
65
65
  - [Defining successes and failures](#defining-successes-and-failures)
66
66
  - [Constant aliases](#constant-aliases)
67
- - [`BCDD::Result::Context.mixin`](#bcddresultcontextmixin)
67
+ - [`BCDD::Context.mixin`](#bcddcontextmixin)
68
68
  - [Class example (Instance Methods)](#class-example-instance-methods-1)
69
69
  - [`and_expose`](#and_expose)
70
70
  - [Module example (Singleton Methods)](#module-example-singleton-methods-1)
71
- - [`BCDD::Result::Context::Expectations`](#bcddresultcontextexpectations)
71
+ - [`BCDD::Context::Expectations`](#bcddcontextexpectations)
72
72
  - [Mixin add-ons](#mixin-add-ons)
73
- - [`BCDD::Result.transitions`](#bcddresulttransitions)
74
- - [Configuration](#configuration)
75
- - [`BCDD::Result.configuration`](#bcddresultconfiguration)
76
- - [`config.addon.enable!(:given, :continue)`](#configaddonenablegiven-continue)
77
- - [`config.constant_alias.enable!('Result', 'BCDD::Context')`](#configconstant_aliasenableresult-bcddcontext)
78
- - [`config.pattern_matching.disable!(:nil_as_valid_value_checking)`](#configpattern_matchingdisablenil_as_valid_value_checking)
79
- - [`config.feature.disable!(:expectations)`](#configfeaturedisableexpectations)
73
+ - [Pattern Matching](#pattern-matching)
74
+ - [`BCDD::Result`](#bcddresult)
75
+ - [`Array`/`Find` patterns](#arrayfind-patterns)
76
+ - [`Hash` patterns](#hash-patterns)
77
+ - [`BCDD::Context`](#bcddcontext-1)
78
+ - [`Array`/`Find` patterns](#arrayfind-patterns-1)
79
+ - [`Hash` patterns](#hash-patterns-1)
80
+ - [How to pattern match without the concept of success and failure](#how-to-pattern-match-without-the-concept-of-success-and-failure)
81
+ - [`BCDD::Result.event_logs`](#bcddresultevent_logs)
82
+ - [`metadata: {ids:}`](#metadata-ids)
83
+ - [Configuration](#configuration)
84
+ - [Turning on/off](#turning-onoff)
85
+ - [Setting a `trace_id` fetcher](#setting-a-trace_id-fetcher)
86
+ - [Setting a `listener`](#setting-a-listener)
87
+ - [Setting multiple `listeners`](#setting-multiple-listeners)
88
+ - [`BCDD::Result.configuration`](#bcddresultconfiguration)
80
89
  - [`BCDD::Result.config`](#bcddresultconfig)
81
90
  - [`BCDD::Result#and_then!`](#bcddresultand_then)
82
91
  - [Dependency Injection](#dependency-injection-1)
@@ -90,9 +99,13 @@ Use it to enable the [Railway Oriented Programming](https://fsharpforfunandprofi
90
99
  - [License](#license)
91
100
  - [Code of Conduct](#code-of-conduct)
92
101
 
93
- ## Ruby Version
102
+ ## Supported Ruby
103
+
104
+ This library is tested against:
94
105
 
95
- `>= 2.7.0`
106
+ Version | 2.7 | 3.0 | 3.1 | 3.2 | 3.3 | Head
107
+ ---- | --- | --- | --- | --- | --- | ---
108
+ 100% Coverage | ✅ | ✅ | ✅ | ✅ | ✅ | ✅
96
109
 
97
110
  ## Installation
98
111
 
@@ -164,7 +177,7 @@ There are other aliases and configurations available. Check the [BCDD::Result.co
164
177
 
165
178
  ## Reference
166
179
 
167
- ### Result Attributes
180
+ ### Basic methods
168
181
 
169
182
  Both `BCDD::Result::Success` and `BCDD::Result::Failure` are composed of the same methods. Look at the basic ones:
170
183
 
@@ -176,20 +189,22 @@ Both `BCDD::Result::Success` and `BCDD::Result::Failure` are composed of the sam
176
189
  ################
177
190
  result = BCDD::Result::Success(:ok, my: 'value')
178
191
 
179
- result.success? # true
180
- result.failure? # false
181
- result.type # :ok
182
- result.value # {:my => "value"}
192
+ result.success? # true
193
+ result.failure? # false
194
+ result.type?(:ok) # true
195
+ result.type # :ok
196
+ result.value # {:my => "value"}
183
197
 
184
198
  ###################
185
199
  # Without a value #
186
200
  ###################
187
201
  result = BCDD::Result::Success(:yes)
188
202
 
189
- result.success? # true
190
- result.failure? # false
191
- result.type # :yes
192
- result.value # nil
203
+ result.success? # true
204
+ result.failure? # false
205
+ result.type?(:yes) # true
206
+ result.type # :yes
207
+ result.value # nil
193
208
  ```
194
209
 
195
210
  **BCDD::Result::Failure**
@@ -200,26 +215,46 @@ result.value # nil
200
215
  ################
201
216
  result = BCDD::Result::Failure(:err, 'my_value')
202
217
 
203
- result.success? # false
204
- result.failure? # true
205
- result.type # :err
206
- result.value # "my_value"
218
+ result.success? # false
219
+ result.failure? # true
220
+ result.type?(:err) # true
221
+ result.type # :err
222
+ result.value # "my_value"
207
223
 
208
224
  ###################
209
225
  # Without a value #
210
226
  ###################
211
227
  result = BCDD::Result::Failure(:no)
212
228
 
213
- result.success? # false
214
- result.failure? # true
215
- result.type # :no
216
- result.value # nil
229
+ result.success? # false
230
+ result.failure? # true
231
+ result.type?(:no) # true
232
+ result.type # :no
233
+ result.value # nil
217
234
  ```
218
235
 
219
236
  In both cases, the `type` must be a symbol, and the `value` can be any kind of object.
220
237
 
221
238
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
222
239
 
240
+ #### Checking types with `result.is?` or `method missing`
241
+
242
+ Beyond the `type?` method, you can also use the `is?` method to check the result type. If you want to check the type directly, you can write the type using a method that ends with a question mark.
243
+
244
+ ```ruby
245
+ result = BCDD::Result::Success(:ok)
246
+
247
+ result.is?(:ok) # true
248
+ result.ok? # true
249
+
250
+ result = BCDD::Result::Failure(:err)
251
+
252
+ result.is?(:err) # true
253
+ result.err? # true
254
+ ```
255
+
256
+ <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
257
+
223
258
  #### Checking types with `result.success?` or `result.failure?`
224
259
 
225
260
  `BCDD::Result#success?` and `BCDD::Result#failure?` are methods that allow you to check if the result is a success or a failure.
@@ -530,67 +565,6 @@ print_to_hash(**success_data) # [:success, :ok, 1]
530
565
 
531
566
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
532
567
 
533
- ### Pattern Matching
534
-
535
- The `BCDD::Result` also provides support to pattern matching.
536
-
537
- In the further examples, I will use the `Divide` lambda to exemplify its usage.
538
-
539
- ```ruby
540
- Divide = lambda do |arg1, arg2|
541
- arg1.is_a?(::Numeric) or return BCDD::Result::Failure(:invalid_arg, 'arg1 must be numeric')
542
- arg2.is_a?(::Numeric) or return BCDD::Result::Failure(:invalid_arg, 'arg2 must be numeric')
543
-
544
- return BCDD::Result::Failure(:division_by_zero, 'arg2 must not be zero') if arg2.zero?
545
-
546
- BCDD::Result::Success(:division_completed, arg1 / arg2)
547
- end
548
- ```
549
-
550
- #### `Array`/`Find` patterns
551
-
552
- ```ruby
553
- case Divide.call(4, 2)
554
- in BCDD::Result::Failure[:invalid_arg, msg] then puts msg
555
- in BCDD::Result::Failure[:division_by_zero, msg] then puts msg
556
- in BCDD::Result::Success[:division_completed, value] then puts value
557
- end
558
-
559
- # The code above will print: 2
560
-
561
- case Divide.call(4, 0)
562
- in BCDD::Result::Failure[:invalid_arg, msg] then puts msg
563
- in BCDD::Result::Failure[:division_by_zero, msg] then puts msg
564
- in BCDD::Result::Success[:division_completed, value] then puts value
565
- end
566
-
567
- # The code above will print: arg2 must not be zero
568
- ```
569
-
570
- <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
571
-
572
- #### `Hash` patterns
573
-
574
- ```ruby
575
- case Divide.call(10, 2)
576
- in { failure: { invalid_arg: msg } } then puts msg
577
- in { failure: { division_by_zero: msg } } then puts msg
578
- in { success: { division_completed: value } } then puts value
579
- end
580
-
581
- # The code above will print: 5
582
-
583
- case Divide.call('10', 2)
584
- in { failure: { invalid_arg: msg } } then puts msg
585
- in { failure: { division_by_zero: msg } } then puts msg
586
- in { success: { division_completed: value } } then puts value
587
- end
588
-
589
- # The code above will print: arg1 must be numeric
590
- ```
591
-
592
- <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
593
-
594
568
  ### Railway Oriented Programming
595
569
 
596
570
  ["Railway Oriented Programming (ROP)"](https://fsharpforfunandprofit.com/rop/) is a programming technique that involves linking blocks together to form a sequence of operations, also known as a pipeline.
@@ -1418,7 +1392,7 @@ result = Divide.new.call(4, 2)
1418
1392
 
1419
1393
  # The example below shows an error because the :ok type is not allowed.
1420
1394
  # But look at the allowed types have only one type (:division_completed).
1421
- # This is because the :continued type is ignored by the expectations.
1395
+ # This is because the :_continue_ type is ignored by the expectations.
1422
1396
  #
1423
1397
  result.success?(:ok)
1424
1398
  # type :ok is not allowed. Allowed types: :division_completed (BCDD::Result::Contract::Error::UnexpectedType)
@@ -1426,45 +1400,45 @@ result.success?(:ok)
1426
1400
 
1427
1401
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1428
1402
 
1429
- ### `BCDD::Result::Context`
1403
+ ### `BCDD::Context`
1430
1404
 
1431
- The `BCDD::Result::Context` is a `BCDD::Result`, meaning it has all the features of the `BCDD::Result`. The main difference is that it only accepts keyword arguments as a value, which applies to the `and_then`: The called methods must receive keyword arguments, and the dependency injection will be performed through keyword arguments.
1405
+ The `BCDD::Context` is a `BCDD::Result`, meaning it has all the features of the `BCDD::Result`. The main difference is that it only accepts keyword arguments as a value, which applies to the `and_then`: The called methods must receive keyword arguments, and the dependency injection will be performed through keyword arguments.
1432
1406
 
1433
- As the input/output are hashes, the results of each `and_then` call will automatically accumulate. This is useful in operations chaining, as the result of the previous operations will be automatically available for the next one. Because of this behavior, the `BCDD::Result::Context` has the `#and_expose` method to expose only the desired keys from the accumulated result.
1407
+ As the input/output are hashes, the results of each `and_then` call will automatically accumulate. This is useful in operations chaining, as the result of the previous operations will be automatically available for the next one. Because of this behavior, the `BCDD::Context` has the `#and_expose` method to expose only the desired keys from the accumulated result.
1434
1408
 
1435
1409
  #### Defining successes and failures
1436
1410
 
1437
- As the `BCDD::Result`, you can declare success and failures directly from `BCDD::Result::Context`.
1411
+ As the `BCDD::Result`, you can declare success and failures directly from `BCDD::Context`.
1438
1412
 
1439
1413
  ```ruby
1440
- BCDD::Result::Context::Success(:ok, a: 1, b: 2)
1441
- #<BCDD::Result::Context::Success type=:ok value={:a=>1, :b=>2}>
1414
+ BCDD::Context::Success(:ok, a: 1, b: 2)
1415
+ #<BCDD::Context::Success type=:ok value={:a=>1, :b=>2}>
1442
1416
 
1443
- BCDD::Result::Context::Failure(:err, message: 'something went wrong')
1444
- #<BCDD::Result::Context::Failure type=:err value={:message=>"something went wrong"}>
1417
+ BCDD::Context::Failure(:err, message: 'something went wrong')
1418
+ #<BCDD::Context::Failure type=:err value={:message=>"something went wrong"}>
1445
1419
  ```
1446
1420
 
1447
- But different from `BCDD::Result` that accepts any value, the `BCDD::Result::Context` only takes keyword arguments.
1421
+ But different from `BCDD::Result` that accepts any value, the `BCDD::Context` only takes keyword arguments.
1448
1422
 
1449
1423
  ```ruby
1450
- BCDD::Result::Context::Success(:ok, [1, 2])
1424
+ BCDD::Context::Success(:ok, [1, 2])
1451
1425
  # wrong number of arguments (given 2, expected 1) (ArgumentError)
1452
1426
 
1453
- BCDD::Result::Context::Failure(:err, { message: 'something went wrong' })
1427
+ BCDD::Context::Failure(:err, { message: 'something went wrong' })
1454
1428
  # wrong number of arguments (given 2, expected 1) (ArgumentError)
1455
1429
 
1456
1430
  #
1457
1431
  # Use ** to convert a hash to keyword arguments
1458
1432
  #
1459
- BCDD::Result::Context::Success(:ok, **{ message: 'hashes can be converted to keyword arguments' })
1460
- #<BCDD::Result::Context::Success type=:ok value={:message=>"hashes can be converted to keyword arguments"}>
1433
+ BCDD::Context::Success(:ok, **{ message: 'hashes can be converted to keyword arguments' })
1434
+ #<BCDD::Context::Success type=:ok value={:message=>"hashes can be converted to keyword arguments"}>
1461
1435
  ```
1462
1436
 
1463
1437
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1464
1438
 
1465
1439
  #### Constant aliases
1466
1440
 
1467
- You can configure `Context` or `BCDD::Context` as an alias for `BCDD::Result::Context`. This is helpful to define a standard way to avoid the full constant name/path in your code.
1441
+ You can configure `Context` or `BCDD::Context` as an alias for `BCDD::Context`. This is helpful to define a standard way to avoid the full constant name/path in your code.
1468
1442
 
1469
1443
  ```ruby
1470
1444
  BCDD::Result.configuration do |config|
@@ -1478,9 +1452,9 @@ end
1478
1452
 
1479
1453
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1480
1454
 
1481
- #### `BCDD::Result::Context.mixin`
1455
+ #### `BCDD::Context.mixin`
1482
1456
 
1483
- As in the `BCDD::Result`, you can use the `BCDD::Result::Context.mixin` to add the `Success()` and `Failure()` methods to your classes/modules.
1457
+ As in the `BCDD::Result`, you can use the `BCDD::Context.mixin` to add the `Success()` and `Failure()` methods to your classes/modules.
1484
1458
 
1485
1459
  Let's see this feature and the data accumulation in action:
1486
1460
 
@@ -1490,7 +1464,7 @@ Let's see this feature and the data accumulation in action:
1490
1464
  require 'logger'
1491
1465
 
1492
1466
  class Divide
1493
- include BCDD::Result::Context.mixin
1467
+ include BCDD::Context.mixin
1494
1468
 
1495
1469
  def call(arg1, arg2, logger: ::Logger.new(STDOUT))
1496
1470
  validate_numbers(arg1, arg2)
@@ -1527,29 +1501,29 @@ end
1527
1501
 
1528
1502
  Divide.new.call(10, 5)
1529
1503
  # I, [2023-10-27T01:51:46.905004 #76915] INFO -- : The division result is 2
1530
- #<BCDD::Result::Context::Success type=:ok value={:number=>2}>
1504
+ #<BCDD::Context::Success type=:ok value={:number=>2}>
1531
1505
 
1532
1506
  Divide.new.call('10', 5)
1533
- #<BCDD::Result::Context::Failure type=:err value={:message=>"arg1 must be numeric"}>
1507
+ #<BCDD::Context::Failure type=:err value={:message=>"arg1 must be numeric"}>
1534
1508
 
1535
1509
  Divide.new.call(10, '5')
1536
- #<BCDD::Result::Context::Failure type=:err value={:message=>"arg2 must be numeric"}>
1510
+ #<BCDD::Context::Failure type=:err value={:message=>"arg2 must be numeric"}>
1537
1511
 
1538
1512
  Divide.new.call(10, 0)
1539
- #<BCDD::Result::Context::Failure type=:err value={:message=>"arg2 must not be zero"}>
1513
+ #<BCDD::Context::Failure type=:err value={:message=>"arg2 must not be zero"}>
1540
1514
  ```
1541
1515
 
1542
1516
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1543
1517
 
1544
1518
  ##### `and_expose`
1545
1519
 
1546
- This allows you to expose only the desired keys from the accumulated result. It can be used with any `BCDD::Result::Context` object.
1520
+ This allows you to expose only the desired keys from the accumulated result. It can be used with any `BCDD::Context` object.
1547
1521
 
1548
1522
  Let's add it to the previous example:
1549
1523
 
1550
1524
  ```ruby
1551
1525
  class Divide
1552
- include BCDD::Result::Context.mixin
1526
+ include BCDD::Context.mixin
1553
1527
 
1554
1528
  def call(arg1, arg2)
1555
1529
  validate_numbers(arg1, arg2)
@@ -1579,7 +1553,7 @@ class Divide
1579
1553
  end
1580
1554
 
1581
1555
  Divide.new.call(10, 5)
1582
- #<BCDD::Result::Context::Success type=:division_completed value={:number=>2}>
1556
+ #<BCDD::Context::Success type=:division_completed value={:number=>2}>
1583
1557
  ```
1584
1558
 
1585
1559
  As you can see, even with `divide` success exposing the division number with all the accumulated data (`**input`), the `#and_expose` could generate a new success with a new type and only with the desired keys.
@@ -1588,7 +1562,7 @@ Remove the `#and_expose` call to see the difference. This will be the outcome:
1588
1562
 
1589
1563
  ```ruby
1590
1564
  Divide.new.call(10, 5)
1591
- #<BCDD::Result::Context::Success type=:ok value={:number=>2, :number1=>10, :number2=>5}>
1565
+ #<BCDD::Context::Success type=:ok value={:number=>2, :number1=>10, :number2=>5}>
1592
1566
  ```
1593
1567
 
1594
1568
  > PS: The `#and_expose` produces a terminal success by default. This means the next step will not be executed even if you call `#and_then` after `#and_expose`. To change this behavior, you can pass `terminal: false` to `#and_expose`.
@@ -1597,11 +1571,11 @@ Divide.new.call(10, 5)
1597
1571
 
1598
1572
  ##### Module example (Singleton Methods)
1599
1573
 
1600
- `BCDD::Result::Context.mixin` can also produce singleton methods. Below is an example using a module (but it could be a class, too).
1574
+ `BCDD::Context.mixin` can also produce singleton methods. Below is an example using a module (but it could be a class, too).
1601
1575
 
1602
1576
  ```ruby
1603
1577
  module Divide
1604
- extend self, BCDD::Result::Context.mixin
1578
+ extend self, BCDD::Context.mixin
1605
1579
 
1606
1580
  def call(arg1, arg2)
1607
1581
  validate_numbers(arg1, arg2)
@@ -1631,29 +1605,29 @@ module Divide
1631
1605
  end
1632
1606
 
1633
1607
  Divide.call(10, 5)
1634
- #<BCDD::Result::Context::Success type=:division_completed value={:number=>2}>
1608
+ #<BCDD::Context::Success type=:division_completed value={:number=>2}>
1635
1609
 
1636
1610
  Divide.call('10', 5)
1637
- #<BCDD::Result::Context::Failure type=:err value={:message=>"arg1 must be numeric"}>
1611
+ #<BCDD::Context::Failure type=:err value={:message=>"arg1 must be numeric"}>
1638
1612
 
1639
1613
  Divide.call(10, '5')
1640
- #<BCDD::Result::Context::Failure type=:err value={:message=>"arg2 must be numeric"}>
1614
+ #<BCDD::Context::Failure type=:err value={:message=>"arg2 must be numeric"}>
1641
1615
 
1642
1616
  Divide.call(10, 0)
1643
- #<BCDD::Result::Context::Failure type=:err value={:message=>"arg2 must not be zero"}>
1617
+ #<BCDD::Context::Failure type=:err value={:message=>"arg2 must not be zero"}>
1644
1618
  ```
1645
1619
 
1646
1620
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1647
1621
 
1648
- #### `BCDD::Result::Context::Expectations`
1622
+ #### `BCDD::Context::Expectations`
1649
1623
 
1650
- The `BCDD::Result::Context::Expectations` is a `BCDD::Result::Expectations` with the `BCDD::Result::Context` features.
1624
+ The `BCDD::Context::Expectations` is a `BCDD::Result::Expectations` with the `BCDD::Context` features.
1651
1625
 
1652
1626
  This is an example using the mixin mode, but the standalone mode is also supported.
1653
1627
 
1654
1628
  ```ruby
1655
1629
  class Divide
1656
- include BCDD::Result::Context::Expectations.mixin(
1630
+ include BCDD::Context::Expectations.mixin(
1657
1631
  config: {
1658
1632
  pattern_matching: { nil_as_valid_value_checking: true }
1659
1633
  },
@@ -1677,16 +1651,16 @@ class Divide
1677
1651
  end
1678
1652
 
1679
1653
  Divide.new.call(10, 5)
1680
- #<BCDD::Result::Context::Success type=:division_completed value={:number=>2}>
1654
+ #<BCDD::Context::Success type=:division_completed value={:number=>2}>
1681
1655
  ```
1682
1656
 
1683
- As in the `BCDD::Result::Expectations.mixin`, the `BCDD::Result::Context::Expectations.mixin` will add a Result constant in the target class. It can generate success/failure results, which ensure the mixin expectations.
1657
+ As in the `BCDD::Result::Expectations.mixin`, the `BCDD::Context::Expectations.mixin` will add a Result constant in the target class. It can generate success/failure results, which ensure the mixin expectations.
1684
1658
 
1685
1659
  Let's see this using the previous example:
1686
1660
 
1687
1661
  ```ruby
1688
1662
  Divide::Result::Success(:division_completed, number: 2)
1689
- #<BCDD::Result::Context::Success type=:division_completed value={:number=>2}>
1663
+ #<BCDD::Context::Success type=:division_completed value={:number=>2}>
1690
1664
 
1691
1665
  Divide::Result::Success(:division_completed, number: '2')
1692
1666
  # value {:number=>"2"} is not allowed for :division_completed type ({:number=>"2"}: Numeric === "2" does not return true) (BCDD::Result::Contract::Error::UnexpectedValue)
@@ -1696,7 +1670,7 @@ Divide::Result::Success(:division_completed, number: '2')
1696
1670
 
1697
1671
  #### Mixin add-ons
1698
1672
 
1699
- The `BCDD::Result::Context.mixin` and `BCDD::Result::Context::Expectations.mixin` also accepts the `config:` argument. And it works the same way as the `BCDD::Result` mixins.
1673
+ The `BCDD::Context.mixin` and `BCDD::Context::Expectations.mixin` also accepts the `config:` argument. And it works the same way as the `BCDD::Result` mixins.
1700
1674
 
1701
1675
  **given**
1702
1676
 
@@ -1704,21 +1678,21 @@ This addon is enabled by default. It will create the `Given(*value)` method. Use
1704
1678
 
1705
1679
  You can turn it off by passing `given: false` to the `config:` argument or using the `BCDD::Result.configuration`.
1706
1680
 
1707
- The `Given()` addon for a BCDD::Result::Context can be called with one or more arguments. The arguments will be converted to a hash (`to_h`) and merged to define the first value of the result chain.
1681
+ The `Given()` addon for a BCDD::Context can be called with one or more arguments. The arguments will be converted to a hash (`to_h`) and merged to define the first value of the result chain.
1708
1682
 
1709
1683
  **continue**
1710
1684
 
1711
- The `BCDD::Result::Context.mixin(config: { addon: { continue: true } })` or `BCDD::Result::Context::Expectations.mixin(config: { addon: { continue: true } })` creates the `Continue(value)` method and change the `Success()` behavior to terminate the step chain.
1685
+ The `BCDD::Context.mixin(config: { addon: { continue: true } })` or `BCDD::Context::Expectations.mixin(config: { addon: { continue: true } })` creates the `Continue(value)` method and change the `Success()` behavior to terminate the step chain.
1712
1686
 
1713
1687
  So, if you want to advance to the next step, you must use `Continue(**value)` instead of `Success(type, **value)`. Otherwise, the step chain will be terminated.
1714
1688
 
1715
- Let's use a mix of `BCDD::Result::Context` features to see in action with this add-on:
1689
+ Let's use a mix of `BCDD::Context` features to see in action with this add-on:
1716
1690
 
1717
1691
  ```ruby
1718
1692
  module Division
1719
1693
  require 'logger'
1720
1694
 
1721
- extend self, BCDD::Result::Context::Expectations.mixin(
1695
+ extend self, BCDD::Context::Expectations.mixin(
1722
1696
  config: {
1723
1697
  addon: { continue: true },
1724
1698
  pattern_matching: { nil_as_valid_value_checking: true }
@@ -1768,33 +1742,193 @@ end
1768
1742
 
1769
1743
  Division.call(14, 2)
1770
1744
  # I, [2023-10-27T02:01:05.812388 #77823] INFO -- : The division result is 7
1771
- #<BCDD::Result::Context::Success type=:division_completed value={:number=>7}>
1745
+ #<BCDD::Context::Success type=:division_completed value={:number=>7}>
1772
1746
 
1773
1747
  Division.call(0, 2)
1774
- ##<BCDD::Result::Context::Success type=:division_completed value={:number=>0}>
1748
+ ##<BCDD::Context::Success type=:division_completed value={:number=>0}>
1775
1749
 
1776
1750
  Division.call('14', 2)
1777
- #<BCDD::Result::Context::Failure type=:invalid_arg value={:message=>"arg1 must be numeric"}>
1751
+ #<BCDD::Context::Failure type=:invalid_arg value={:message=>"arg1 must be numeric"}>
1778
1752
 
1779
1753
  Division.call(14, '2')
1780
- #<BCDD::Result::Context::Failure type=:invalid_arg value={:message=>"arg2 must be numeric"}>
1754
+ #<BCDD::Context::Failure type=:invalid_arg value={:message=>"arg2 must be numeric"}>
1781
1755
 
1782
1756
  Division.call(14, 0)
1783
- #<BCDD::Result::Context::Failure type=:division_by_zero value={:message=>"arg2 must not be zero"}>
1757
+ #<BCDD::Context::Failure type=:division_by_zero value={:message=>"arg2 must not be zero"}>
1758
+ ```
1759
+
1760
+ <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1761
+
1762
+ ## Pattern Matching
1763
+
1764
+ The `BCDD::Result` and `BCDD::Context` also provides support to pattern matching.
1765
+
1766
+ ### `BCDD::Result`
1767
+
1768
+ In the further examples, I will use the `Divide` lambda to exemplify its usage.
1769
+
1770
+ ```ruby
1771
+ Divide = lambda do |arg1, arg2|
1772
+ arg1.is_a?(::Numeric) or return BCDD::Result::Failure(:invalid_arg, 'arg1 must be numeric')
1773
+ arg2.is_a?(::Numeric) or return BCDD::Result::Failure(:invalid_arg, 'arg2 must be numeric')
1774
+
1775
+ return BCDD::Result::Failure(:division_by_zero, 'arg2 must not be zero') if arg2.zero?
1776
+
1777
+ BCDD::Result::Success(:division_completed, arg1 / arg2)
1778
+ end
1779
+ ```
1780
+
1781
+ #### `Array`/`Find` patterns
1782
+
1783
+ ```ruby
1784
+ case Divide.call(4, 2)
1785
+ in BCDD::Failure[:invalid_arg, msg] then puts msg
1786
+ in BCDD::Failure[:division_by_zero, msg] then puts msg
1787
+ in BCDD::Success[:division_completed, num] then puts num
1788
+ end
1789
+
1790
+ # The code above will print: 2
1791
+
1792
+ case Divide.call(4, 0)
1793
+ in BCDD::Failure[:invalid_arg, msg] then puts msg
1794
+ in BCDD::Failure[:division_by_zero, msg] then puts msg
1795
+ in BCDD::Success[:division_completed, num] then puts num
1796
+ end
1797
+
1798
+ # The code above will print: arg2 must not be zero
1799
+ ```
1800
+
1801
+ <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1802
+
1803
+ #### `Hash` patterns
1804
+
1805
+ ```ruby
1806
+ case Divide.call(10, 2)
1807
+ in BCDD::Failure(type: :invalid_arg, value: msg) then puts msg
1808
+ in BCDD::Failure(type: :division_by_zero, value: msg) then puts msg
1809
+ in BCDD::Success(type: :division_completed, value: num) then puts num
1810
+ end
1811
+
1812
+ # The code above will print: 5
1813
+
1814
+ case Divide.call('10', 2)
1815
+ in BCDD::Failure(type: :invalid_arg, value: msg) then puts msg
1816
+ in BCDD::Failure(type: :division_by_zero, value: msg) then puts msg
1817
+ in BCDD::Success(type: :division_completed, value: num) then puts num
1818
+ end
1819
+
1820
+ # The code above will print: arg1 must be numeric
1821
+ ```
1822
+
1823
+ You can also use `BCDD::Result::Success` and `BCDD::Result::Failure` as patterns.
1824
+
1825
+ <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1826
+
1827
+
1828
+ ### `BCDD::Context`
1829
+
1830
+ In the further examples, I will use the `Divide` lambda to exemplify its usage.
1831
+
1832
+ ```ruby
1833
+ Divide = lambda do |arg1, arg2|
1834
+ arg1.is_a?(::Numeric) or return BCDD::Context::Failure(:invalid_arg, err: 'arg1 must be numeric')
1835
+ arg2.is_a?(::Numeric) or return BCDD::Context::Failure(:invalid_arg, err: 'arg2 must be numeric')
1836
+
1837
+ return BCDD::Context::Failure(:division_by_zero, err: 'arg2 must not be zero') if arg2.zero?
1838
+
1839
+ BCDD::Context::Success(:division_completed, num: arg1 / arg2)
1840
+ end
1841
+ ```
1842
+
1843
+ #### `Array`/`Find` patterns
1844
+
1845
+ ```ruby
1846
+ case Divide.call(4, 2)
1847
+ in BCDD::Failure[:invalid_arg, {msg:}] then puts msg
1848
+ in BCDD::Failure[:division_by_zero, {msg:}] then puts msg
1849
+ in BCDD::Success[:division_completed, {num:}] then puts num
1850
+ end
1851
+
1852
+ # The code above will print: 2
1853
+
1854
+ case Divide.call(4, 0)
1855
+ in BCDD::Failure[:invalid_arg, {msg:}] then puts msg
1856
+ in BCDD::Failure[:division_by_zero, {msg:}] then puts msg
1857
+ in BCDD::Success[:division_completed, {num:}] then puts num
1858
+ end
1859
+
1860
+ # The code above will print: arg2 must not be zero
1861
+ ```
1862
+
1863
+ <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1864
+
1865
+ #### `Hash` patterns
1866
+
1867
+ If you don't provide the keys :type and :value, the pattern will match the result value.
1868
+
1869
+ ```ruby
1870
+ case Divide.call(10, 2)
1871
+ in BCDD::Failure({msg:}) then puts msg
1872
+ in BCDD::Success({num:}) then puts num
1873
+ end
1874
+ ```
1875
+
1876
+ ```ruby
1877
+ case Divide.call(10, 2)
1878
+ in BCDD::Failure(type: :invalid_arg, value: {msg:}) then puts msg
1879
+ in BCDD::Failure(type: :division_by_zero, value: {msg:}) then puts msg
1880
+ in BCDD::Success(type: :division_completed, value: {num:}) then puts num
1881
+ end
1882
+
1883
+ # The code above will print: 5
1884
+
1885
+ case Divide.call('10', 2)
1886
+ in BCDD::Failure(type: :invalid_arg, value: {msg:}) then puts {msg:}
1887
+ in BCDD::Failure(type: :division_by_zero, value: {msg:}) then puts msg
1888
+ in BCDD::Success(type: :division_completed, value: {num:}) then puts num
1889
+ end
1890
+
1891
+ # The code above will print: arg1 must be numeric
1892
+ ```
1893
+
1894
+ You can also use `BCDD::Context::Success` and `BCDD::Context::Failure` as patterns.
1895
+
1896
+ <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1897
+
1898
+ ### How to pattern match without the concept of success and failure
1899
+
1900
+ You can use the classes `BCDD::Result` and `BCDD::Context` as patterns, and the pattern matching will work without the concept of success and failure.
1901
+
1902
+ ```ruby
1903
+ case Divide.call(10, 2)
1904
+ in BCDD::Context(:invalid_arg, {msg:}) then puts msg
1905
+ in BCDD::Context(:division_by_zero, {msg:}) then puts msg
1906
+ in BCDD::Context(:division_completed, {num:}) then puts num
1907
+ end
1908
+
1909
+ case Divide.call(10, 2)
1910
+ in BCDD::Result(:invalid_arg, msg) then puts msg
1911
+ in BCDD::Result(:division_by_zero, msg) then puts msg
1912
+ in BCDD::Result(:division_completed, num) then puts num
1913
+ end
1784
1914
  ```
1785
1915
 
1786
- ### `BCDD::Result.transitions`
1916
+ The `BCDD::Result` will also work with the `BCDD::Context`, but the opposite won't.
1917
+
1918
+ <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1919
+
1920
+ ## `BCDD::Result.event_logs`
1787
1921
 
1788
- Use `BCDD::Result.transitions(&block)` to track all transitions in the same or between different operations (it works with `BCDD::Result` and `BCDD::Result::Context`). When there is a nesting of transition blocks, this mechanism will be able to correlate parent and child blocks and present the duration of all operations in milliseconds.
1922
+ Use `BCDD::Result.event_logs(&block)` to track all the results produced in the same or between different operations (it works with `BCDD::Result` and `BCDD::Context`). When there is a nesting of `event_logs` blocks, this mechanism will be able to correlate parent and child blocks and present the duration of all operations in milliseconds.
1789
1923
 
1790
- When you wrap the creation of the result with `BCDD::Result.transitions`, the final result will expose all the transition records through the `BCDD::Result#transitions` method.
1924
+ When you wrap the creation of the result with `BCDD::Result.event_logs`, the final one will expose all the event log records through the `BCDD::Result#event_logs` method.
1791
1925
 
1792
1926
  ```ruby
1793
1927
  class Division
1794
1928
  include BCDD::Result.mixin(config: { addon: { continue: true } })
1795
1929
 
1796
1930
  def call(arg1, arg2)
1797
- BCDD::Result.transitions(name: 'Division', desc: 'divide two numbers') do
1931
+ BCDD::Result.event_logs(name: 'Division', desc: 'divide two numbers') do
1798
1932
  Given([arg1, arg2])
1799
1933
  .and_then(:require_numbers)
1800
1934
  .and_then(:check_for_zeros)
@@ -1804,7 +1938,7 @@ class Division
1804
1938
 
1805
1939
  private
1806
1940
 
1807
- ValidNumber = ->(arg) { arg.is_a?(Numeric) && arg != Float::NAN && arg != Float::INFINITY }
1941
+ ValidNumber = ->(arg) { arg.is_a?(Numeric) && (!arg.respond_to?(:finite?) || arg.finite?) }
1808
1942
 
1809
1943
  def require_numbers((arg1, arg2))
1810
1944
  ValidNumber[arg1] or return Failure(:invalid_arg, 'arg1 must be a valid number')
@@ -1830,7 +1964,7 @@ module SumDivisionsByTwo
1830
1964
  extend self, BCDD::Result.mixin
1831
1965
 
1832
1966
  def call(*numbers)
1833
- BCDD::Result.transitions(name: 'SumDivisionsByTwo') do
1967
+ BCDD::Result.event_logs(name: 'SumDivisionsByTwo') do
1834
1968
  divisions = numbers.map { |number| Division.new.call(number, 2) }
1835
1969
 
1836
1970
  if divisions.any?(&:failure?)
@@ -1849,85 +1983,90 @@ Let's see the result of the `SumDivisionsByTwo` call:
1849
1983
  result = SumDivisionsByTwo.call(20, 10)
1850
1984
  # => #<BCDD::Result::Success type=:sum value=15>
1851
1985
 
1852
- result.transitions
1986
+ result.event_logs
1853
1987
  {
1854
- :version =>1,
1988
+ :version => 1,
1855
1989
  :metadata => {
1856
- :duration => 0, # milliseconds
1857
- :tree_map => [0, [[1, []], [2, []]]], # represents the tree of transitions using the id of each transition block
1990
+ :duration => 0, # milliseconds
1991
+ :trace_id => nil, # can be set through configuration
1992
+ :ids => {
1993
+ :tree => [0, [[1, []], [2, []]]],
1994
+ :matrix => { 0 => [0, 0], 1 => [1, 1], 2 => [2, 1]},
1995
+ :level_parent => { 0 => [0, 0], 1 => [1, 0], 2 => [1, 0]}
1996
+ }
1858
1997
  },
1859
- :records => [
1998
+ :records=> [
1860
1999
  {
1861
- :root=>{:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
1862
- :parent=>{:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
1863
- :current=>{:id=>1, :name=>"Division", :desc=>"divide two numbers"},
1864
- :result=>{:kind=>:success, :type=>:given, :value=>[20, 2]},
1865
- :and_then=>{},
1866
- :time=>2024-01-02 03:35:11.248418 UTC
2000
+ :root => {:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
2001
+ :parent => {:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
2002
+ :current => {:id=>1, :name=>"Division", :desc=>"divide two numbers"},
2003
+ :result => {:kind=>:success, :type=>:_given_, :value=>[20, 2], :source=><Division:0x0000000102fd7ed0>},
2004
+ :and_then => {},
2005
+ :time => 2024-01-26 02:53:11.310346 UTC
1867
2006
  },
1868
2007
  {
1869
- :root=>{:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
1870
- :parent=>{:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
1871
- :current=>{:id=>1, :name=>"Division", :desc=>"divide two numbers"},
1872
- :result=>{:kind=>:success, :type=>:continued, :value=>[20, 2]},
1873
- :and_then=>{:type=>:method, :arg=>nil, :source=><Division:0x0000000106099028>, :method_name=>:require_numbers},
1874
- :time=>2024-01-02 03:35:11.248558 UTC
2008
+ :root => {:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
2009
+ :parent => {:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
2010
+ :current => {:id=>1, :name=>"Division", :desc=>"divide two numbers"},
2011
+ :result => {:kind=>:success, :type=>:_continue_, :value=>[20, 2], :source=><Division:0x0000000102fd7ed0>},
2012
+ :and_then => {:type=>:method, :arg=>nil, :method_name=>:require_numbers},
2013
+ :time => 2024-01-26 02:53:11.310392 UTC
1875
2014
  },
1876
2015
  {
1877
- :root=>{:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
1878
- :parent=>{:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
1879
- :current=>{:id=>1, :name=>"Division", :desc=>"divide two numbers"},
1880
- :result=>{:kind=>:success, :type=>:continued, :value=>[20, 2]},
1881
- :and_then=>{:type=>:method, :arg=>nil, :source=><Division:0x0000000106099028>, :method_name=>:check_for_zeros},
1882
- :time=>2024-01-02 03:35:11.248587 UTC
2016
+ :root => {:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
2017
+ :parent => {:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
2018
+ :current => {:id=>1, :name=>"Division", :desc=>"divide two numbers"},
2019
+ :result => {:kind=>:success, :type=>:_continue_, :value=>[20, 2], :source=><Division:0x0000000102fd7ed0>},
2020
+ :and_then => {:type=>:method, :arg=>nil, :method_name=>:check_for_zeros},
2021
+ :time=>2024-01-26 02:53:11.310403 UTC
1883
2022
  },
1884
2023
  {
1885
- :root=>{:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
1886
- :parent=>{:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
1887
- :current=>{:id=>1, :name=>"Division", :desc=>"divide two numbers"},
1888
- :result=>{:kind=>:success, :type=>:division_completed, :value=>10},
1889
- :and_then=>{:type=>:method, :arg=>nil, :source=><Division:0x0000000106099028>, :method_name=>:divide},
1890
- :time=>2024-01-02 03:35:11.248607 UTC
2024
+ :root => {:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
2025
+ :parent => {:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
2026
+ :current => {:id=>1, :name=>"Division", :desc=>"divide two numbers"},
2027
+ :result => {:kind=>:success, :type=>:division_completed, :value=>10, :source=><Division:0x0000000102fd7ed0>},
2028
+ :and_then => {:type=>:method, :arg=>nil, :method_name=>:divide},
2029
+ :time => 2024-01-26 02:53:11.310409 UTC
1891
2030
  },
1892
2031
  {
1893
- :root=>{:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
1894
- :parent=>{:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
1895
- :current=>{:id=>2, :name=>"Division", :desc=>"divide two numbers"},
1896
- :result=>{:kind=>:success, :type=>:given, :value=>[10, 2]},
1897
- :and_then=>{},
1898
- :time=>2024-01-02 03:35:11.24865 UTC
2032
+ :root => {:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
2033
+ :parent => {:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
2034
+ :current => {:id=>2, :name=>"Division", :desc=>"divide two numbers"},
2035
+ :result => {:kind=>:success, :type=>:_given_, :value=>[10, 2], :source=><Division:0x0000000102fd6378>},
2036
+ :and_then => {},
2037
+ :time => 2024-01-26 02:53:11.310424 UTC
1899
2038
  },
1900
2039
  {
1901
- :root=>{:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
1902
- :parent=>{:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
1903
- :current=>{:id=>2, :name=>"Division", :desc=>"divide two numbers"},
1904
- :result=>{:kind=>:success, :type=>:continued, :value=>[10, 2]},
1905
- :and_then=>{:type=>:method, :arg=>nil, :source=><Division:0x0000000106097ed0>, :method_name=>:require_numbers},
1906
- :time=>2024-01-02 03:35:11.248661 UTC
2040
+ :root => {:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
2041
+ :parent => {:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
2042
+ :current => {:id=>2, :name=>"Division", :desc=>"divide two numbers"},
2043
+ :result => {:kind=>:success, :type=>:_continue_, :value=>[10, 2], :source=><Division:0x0000000102fd6378>},
2044
+ :and_then => {:type=>:method, :arg=>nil, :method_name=>:require_numbers},
2045
+ :time => 2024-01-26 02:53:11.310428 UTC
1907
2046
  },
1908
2047
  {
1909
- :root=>{:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
1910
- :parent=>{:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
1911
- :current=>{:id=>2, :name=>"Division", :desc=>"divide two numbers"},
1912
- :result=>{:kind=>:success, :type=>:continued, :value=>[10, 2]},
1913
- :and_then=>{:type=>:method, :arg=>nil, :source=><Division:0x0000000106097ed0>, :method_name=>:check_for_zeros},
1914
- :time=>2024-01-02 03:35:11.248672 UTC
2048
+ :root => {:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
2049
+ :parent => {:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
2050
+ :current => {:id=>2, :name=>"Division", :desc=>"divide two numbers"},
2051
+ :result => {:kind=>:success, :type=>:_continue_, :value=>[10, 2], :source=><Division:0x0000000102fd6378>},
2052
+ :and_then => {:type=>:method, :arg=>nil, :method_name=>:check_for_zeros},
2053
+ :time => 2024-01-26 02:53:11.310431 UTC
1915
2054
  },
1916
2055
  {
1917
- :root=>{:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
1918
- :parent=>{:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
1919
- :current=>{:id=>2, :name=>"Division", :desc=>"divide two numbers"},
1920
- :result=>{:kind=>:success, :type=>:division_completed, :value=>5},
1921
- :and_then=>{:type=>:method, :arg=>nil, :source=><Division:0x0000000106097ed0>, :method_name=>:divide},
1922
- :time=>2024-01-02 03:35:11.248682 UTC
2056
+ :root => {:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
2057
+ :parent => {:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
2058
+ :current => {:id=>2, :name=>"Division", :desc=>"divide two numbers"},
2059
+ :result => {:kind=>:success, :type=>:division_completed, :value=>5, :source=><Division:0x0000000102fd6378>},
2060
+ :and_then => {:type=>:method, :arg=>nil, :method_name=>:divide},
2061
+ :time => 2024-01-26 02:53:11.310434 UTC
1923
2062
  },
1924
2063
  {
1925
- :root=>{:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
1926
- :parent=>{:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
1927
- :current=>{:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
1928
- :result=>{:kind=>:success, :type=>:sum, :value=>15},
1929
- :and_then=>{},
1930
- :time=>2024-01-02 03:35:11.248721 UTC
2064
+ :root => {:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
2065
+ :parent => {:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
2066
+ :current => {:id=>0, :name=>"SumDivisionsByTwo", :desc=>nil},
2067
+ :result => {:kind=>:success, :type=>:sum, :value=>15, :source=>SumDivisionsByTwo},
2068
+ :and_then => {},
2069
+ :time => 2024-01-26 02:53:11.310444 UTC
1931
2070
  }
1932
2071
  ]
1933
2072
  }
@@ -1935,28 +2074,260 @@ result.transitions
1935
2074
 
1936
2075
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1937
2076
 
1938
- #### Configuration
2077
+ ### `metadata: {ids:}`
2078
+
2079
+ The `:ids` metadata property is a hash with three properties:
2080
+ - `:tree`, a graph/tree representation of the id of each `event_logs` block.
2081
+ - `:level_parent`, a hash with the level (depth) of each block and its parent id.
2082
+ - `:matrix`, a matrix representation of the event logs ids. It is a simplification of the `:tree` property.
1939
2083
 
1940
- You can use `BCDD::Result.config.feature.disable!(:transitions)` and `BCDD::Result.config.feature.enable!(:transitions)` to turn on/off the `BCDD::Result.transitions` feature.
2084
+ Use these data structures to build your own visualization.
2085
+
2086
+ > Check out [Event Logs Listener example](examples/single_listener/lib/single_event_logs_listener.rb) to see how a listener can be used to build a STDOUT visualization, using these properties.
2087
+
2088
+ ```ruby
2089
+ # tree:
2090
+ # A graph representation (array of arrays) of the each event logs block id.
2091
+ #
2092
+ 0 # [0, [
2093
+ |- 1 # [1, [[2, []]]],
2094
+ | |- 2 # [3, []],
2095
+ |- 3 # [4, [
2096
+ |- 4 # [5, []],
2097
+ | |- 5 # [6, [[7, []]]]
2098
+ | |- 6 # ]],
2099
+ | |- 7 # [8, []]
2100
+ |- 8 # ]]
2101
+
2102
+ # level_parent:
2103
+ # The event logs ids are the keys, and the level (depth) and parent id the values.
2104
+ # {
2105
+ 0 # 0 => [0, 0],
2106
+ |- 1 # 1 => [1, 0],
2107
+ | |- 2 # 2 => [2, 1],
2108
+ |- 3 # 3 => [1, 0],
2109
+ |- 4 # 4 => [1, 0],
2110
+ | |- 5 # 5 => [2, 4],
2111
+ | |- 6 # 6 => [2, 4],
2112
+ | |- 7 # 7 => [3, 6],
2113
+ |- 8 # 8 => [1, 0]
2114
+ # }
2115
+
2116
+ # matrix:
2117
+ # The rows are the direct blocks from the root block,
2118
+ # and the columns are the nested blocks from the direct ones.
2119
+ # {
2120
+ 0 | 1 | 2 | 3 | 4 # 0 => [0, 0],
2121
+ - | - | - | - | - # 1 => [1, 1],
2122
+ 0 | | | | # 2 => [1, 2],
2123
+ 1 | 1 | 2 | | # 3 => [2, 1],
2124
+ 2 | 3 | | | # 4 => [3, 1],
2125
+ 3 | 4 | 5 | 6 | 7 # 5 => [3, 2],
2126
+ 4 | 8 | | | # 6 => [3, 3],
2127
+ # 7 => [3, 4],
2128
+ # 8 => [4, 1]
2129
+ # }
2130
+ ```
2131
+
2132
+ <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
2133
+
2134
+ ### Configuration
2135
+
2136
+ #### Turning on/off
2137
+
2138
+ You can use `BCDD::Result.config.feature.disable!(event_logs)` and `BCDD::Result.config.feature.enable!(event_logs)` to turn on/off the `BCDD::Result.event_logs` feature.
1941
2139
 
1942
2140
  ```ruby
1943
2141
  BCDD::Result.configuration do |config|
1944
- config.feature.disable!(:transitions)
2142
+ config.feature.disable!(event_logs)
1945
2143
  end
1946
2144
 
1947
2145
  result = SumDivisionsByTwo.call(20, 10)
1948
2146
  # => #<BCDD::Result::Success type=:sum value=15>
1949
2147
 
1950
- result.transitions
2148
+ result.event_logs
2149
+ {
2150
+ :version=>1,
2151
+ :records=>[],
2152
+ :metadata=>{
2153
+ :duration=>0,
2154
+ :ids=>{:tree=>[], :matrix=>{}, :level_parent=>{}}, :trace_id=>nil
2155
+ }
2156
+ }
2157
+ ```
2158
+
2159
+ <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
2160
+
2161
+ #### Setting a `trace_id` fetcher
1951
2162
 
1952
- {:version=>1, :records=>[], :metadata=>{:duration=>0, :tree_map=>[]}}
2163
+ You can define a lambda (arity 0) to fetch the trace_id. This lambda will be called before the first event logs block and will be used to set the `:trace_id` in the `:metadata` property.
2164
+
2165
+ Use to correlate different or the same operation (executed multiple times).
2166
+
2167
+ ```ruby
2168
+ BCDD::Result.config.event_logs.trace_id = -> { Thread.current[:bcdd_result_event_logs_trace_id] }
1953
2169
  ```
1954
2170
 
1955
2171
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1956
2172
 
1957
- ### `BCDD::Result.configuration`
2173
+ #### Setting a `listener`
2174
+
2175
+ You can define a listener to be called during the event logs tracking (check out [this example](examples/single_listener/lib/single_event_logs_listener.rb)). It must be a class that includes `BCDD::Result::EventLogs::Listener`.
2176
+
2177
+ Use it to build your additional logic on top of the tracking. Examples:
2178
+ - Log the event logs.
2179
+ - Perform the tracing.
2180
+ - Instrument the event logs (measure/report).
2181
+ - Build a visualization (Diagrams, using the `records:` + `metadata: {ids:}` properties).
2182
+
2183
+ After implementing your listener, you can set it to the `BCDD::Result.config.event_logs.listener=`:
2184
+
2185
+ ```ruby
2186
+ BCDD::Result.config.event_logs.listener = MyEventLogsListener
2187
+ ```
1958
2188
 
1959
- The `BCDD::Result.configuration` allows you to configure default behaviors for `BCDD::Result` and `BCDD::Result::Context` through a configuration block. After using it, the configuration is frozen, ensuring the expected behaviors for your application.
2189
+ See the example below to understand how to implement one:
2190
+
2191
+ ```ruby
2192
+ class MyEventLogsListener
2193
+ include BCDD::Result::EventLogs::Listener
2194
+
2195
+ # A listener will be initialized before the first event logs block, and it is discarded after the last one.
2196
+ def initialize
2197
+ end
2198
+
2199
+ # This method will be called before each event logs block.
2200
+ # The parent block will be called first in the case of nested ones.
2201
+ #
2202
+ # @param scope: {:id=>1, :name=>"SomeOperation", :desc=>"Optional description"}
2203
+ def on_start(scope:)
2204
+ end
2205
+
2206
+ # This method will wrap all the event logs in the same block.
2207
+ # It can be used to perform an instrumentation (measure/report).
2208
+ #
2209
+ # @param scope: {:id=>1, :name=>"SomeOperation", :desc=>"Optional description"}
2210
+ def around_event_logs(scope:)
2211
+ yield
2212
+ end
2213
+
2214
+ # This method will wrap each and_then call.
2215
+ # It can be used to perform an instrumentation of the and_then calls.
2216
+ #
2217
+ # @param scope: {:id=>1, :name=>"SomeOperation", :desc=>"Optional description"}
2218
+ # @param and_then:
2219
+ # {:type=>:block, :arg=>:some_injected_value}
2220
+ # {:type=>:method, :arg=>:some_injected_value, :method_name=>:some_method_name}
2221
+ def around_and_then(scope:, and_then:)
2222
+ yield
2223
+ end
2224
+
2225
+ # This method will be called after each result recording/tracking.
2226
+ #
2227
+ # @param record:
2228
+ # {
2229
+ # :root => {:id=>0, :name=>"RootOperation", :desc=>nil},
2230
+ # :parent => {:id=>0, :name=>"RootOperation", :desc=>nil},
2231
+ # :current => {:id=>1, :name=>"SomeOperation", :desc=>nil},
2232
+ # :result => {:kind=>:success, :type=>:_continue_, :value=>{some: :thing}, :source=><MyProcess:0x0000000102fd6378>},
2233
+ # :and_then => {:type=>:method, :arg=>nil, :method_name=>:some_method},
2234
+ # :time => 2024-01-26 02:53:11.310431 UTC
2235
+ # }
2236
+ def on_record(record:)
2237
+ end
2238
+
2239
+ # This method will be called at the end of the event logs tracking.
2240
+ #
2241
+ # @param event_logs:
2242
+ # {
2243
+ # :version => 1,
2244
+ # :metadata => {
2245
+ # :duration => 0,
2246
+ # :trace_id => nil,
2247
+ # :ids => {
2248
+ # :tree => [0, [[1, []], [2, []]]],
2249
+ # :matrix => { 0 => [0, 0], 1 => [1, 1], 2 => [2, 1]},
2250
+ # :level_parent => { 0 => [0, 0], 1 => [1, 0], 2 => [1, 0]}
2251
+ # }
2252
+ # },
2253
+ # :records => [
2254
+ # # ...
2255
+ # ]
2256
+ # }
2257
+ def on_finish(event_logs:)
2258
+ end
2259
+
2260
+ # This method will be called when an exception is raised during the event logs tracking.
2261
+ #
2262
+ # @param exception: Exception
2263
+ # @param event_logs: Hash
2264
+ def before_interruption(exception:, event_logs:)
2265
+ end
2266
+ end
2267
+ ```
2268
+
2269
+ <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
2270
+
2271
+ #### Setting multiple `listeners`
2272
+
2273
+ You can use `BCDD::Result::EventLogs::Listeners[]` to creates a listener of listeners (check out [this example](examples/multiple_listeners/Rakefile)), which will be called in the order they were added.
2274
+
2275
+ **Attention:** It only allows one listener to handle `around_and_then` and another `around_event_logs` records.
2276
+
2277
+ > The example below defines different listeners to handle `around_and_then` and `around_event_logs,` but it is also possible to define a listener to handle both.
2278
+
2279
+ ```ruby
2280
+ class AroundAndThenListener
2281
+ include BCDD::Result::EventLogs::Listener
2282
+
2283
+ # It must be a static/singleton method.
2284
+ def self.around_and_then?
2285
+ true
2286
+ end
2287
+
2288
+ def around_and_then(scope:, and_then:)
2289
+ #...
2290
+ end
2291
+ end
2292
+
2293
+ class AroundEventLogsListener
2294
+ include BCDD::Result::EventLogs::Listener
2295
+
2296
+ # It must be a static/singleton method.
2297
+ def self.around_event_logs?
2298
+ true
2299
+ end
2300
+
2301
+ def around_event_logs(scope:)
2302
+ #...
2303
+ end
2304
+ end
2305
+
2306
+ class MyEventLogsListener
2307
+ include BCDD::Result::EventLogs::Listener
2308
+ end
2309
+ ```
2310
+
2311
+ How to use it:
2312
+
2313
+ ```ruby
2314
+ # The listeners will be called in the order they were added.
2315
+ BCDD::Result.config.event_logs.listener = BCDD::Result::EventLogs::Listeners[
2316
+ MyEventLogsListener,
2317
+ AroundAndThenListener,
2318
+ AroundEventLogsListener
2319
+ ]
2320
+ ```
2321
+
2322
+ > Check out [this example](examples/multiple_listeners) to see a listener to print the event logs and another to store them in the database.
2323
+
2324
+ <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
2325
+
2326
+ ## `BCDD::Result.configuration`
2327
+
2328
+ The `BCDD::Result.configuration` allows you to configure default behaviors for `BCDD::Result` and `BCDD::Context` through a configuration block. After using it, the configuration is frozen, ensuring the expected behaviors for your application.
2329
+
2330
+ > Note: You can use `BCDD::Result.configuration(freeze: false) {}` to avoid the freezing. This can be useful in tests. Please be sure to use it with caution.
1960
2331
 
1961
2332
  ```ruby
1962
2333
  BCDD::Result.configuration do |config|
@@ -1974,37 +2345,37 @@ Use `disable!` to disable a feature and `enable!` to enable it.
1974
2345
 
1975
2346
  Let's see what each configuration in the example above does:
1976
2347
 
1977
- #### `config.addon.enable!(:given, :continue)`
2348
+ ### `config.addon.enable!(:given, :continue)` <!-- omit in toc -->
1978
2349
 
1979
- This configuration enables the `Continue()` method for `BCDD::Result.mixin`, `BCDD::Result::Context.mixin`, `BCDD::Result::Expectation.mixin`, and `BCDD::Result::Context::Expectation.mixin`. Link to documentations: [(1)](#add-ons) [(2)](#mixin-add-ons).
2350
+ This configuration enables the `Continue()` method for `BCDD::Result.mixin`, `BCDD::Context.mixin`, `BCDD::Result::Expectation.mixin`, and `BCDD::Context::Expectation.mixin`. Link to documentations: [(1)](#add-ons) [(2)](#mixin-add-ons).
1980
2351
 
1981
2352
  It is also enabling the `Given()` which is already enabled by default. Link to documentation: [(1)](#add-ons) [(2)](#mixin-add-ons).
1982
2353
 
1983
- #### `config.constant_alias.enable!('Result', 'BCDD::Context')`
2354
+ ### `config.constant_alias.enable!('Result', 'BCDD::Context')` <!-- omit in toc -->
1984
2355
 
1985
- This configuration make `Result` a constant alias for `BCDD::Result`, and `BCDD::Context` a constant alias for `BCDD::Result::Context`.
2356
+ This configuration make `Result` a constant alias for `BCDD::Result`, and `BCDD::Context` a constant alias for `BCDD::Context`.
1986
2357
 
1987
2358
  Link to documentations:
1988
2359
  - [Result alias](#bcddresult-versus-result)
1989
2360
  - [Context aliases](#constant-aliases)
1990
2361
 
1991
- #### `config.pattern_matching.disable!(:nil_as_valid_value_checking)`
2362
+ ### `config.pattern_matching.disable!(:nil_as_valid_value_checking)` <!-- omit in toc -->
1992
2363
 
1993
- This configuration disables the `nil_as_valid_value_checking` for `BCDD::Result` and `BCDD::Result::Context`. Link to [documentation](#pattern-matching-support).
2364
+ This configuration disables the `nil_as_valid_value_checking` for `BCDD::Result` and `BCDD::Context`. Link to [documentation](#pattern-matching-support).
1994
2365
 
1995
- <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1996
-
1997
- #### `config.feature.disable!(:expectations)`
2366
+ ### `config.feature.disable!(:expectations)` <!-- omit in toc -->
1998
2367
 
1999
- This configuration turns off the expectations for `BCDD::Result` and `BCDD::Result::Context`. The expectations are helpful in development and test environments, but they can be disabled in production environments for performance gain.
2368
+ This configuration turns off the expectations for `BCDD::Result` and `BCDD::Context`. The expectations are helpful in development and test environments, but they can be disabled in production environments for performance gain.
2000
2369
 
2001
2370
  PS: I'm using `::Rails.env.production?` to check the environment, but you can use any logic you want.
2002
2371
 
2372
+ <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
2373
+
2003
2374
  ### `BCDD::Result.config`
2004
2375
 
2005
2376
  The `BCDD::Result.config` allows you to access the current configuration.
2006
2377
 
2007
- **BCDD::Result.config.addon**
2378
+ #### **BCDD::Result.config.addon** <!-- omit in toc -->
2008
2379
 
2009
2380
  ```ruby
2010
2381
  BCDD::Result.config.addon.enabled?(:continue)
@@ -2016,24 +2387,24 @@ BCDD::Result.config.addon.options
2016
2387
  # :enabled=>false,
2017
2388
  # :affects=>[
2018
2389
  # "BCDD::Result.mixin",
2019
- # "BCDD::Result::Context.mixin",
2390
+ # "BCDD::Context.mixin",
2020
2391
  # "BCDD::Result::Expectations.mixin",
2021
- # "BCDD::Result::Context::Expectations.mixin"
2392
+ # "BCDD::Context::Expectations.mixin"
2022
2393
  # ]
2023
2394
  # },
2024
2395
  # :given=>{
2025
2396
  # :enabled=>true,
2026
2397
  # :affects=>[
2027
2398
  # "BCDD::Result.mixin",
2028
- # "BCDD::Result::Context.mixin",
2399
+ # "BCDD::Context.mixin",
2029
2400
  # "BCDD::Result::Expectations.mixin",
2030
- # "BCDD::Result::Context::Expectations.mixin"
2401
+ # "BCDD::Context::Expectations.mixin"
2031
2402
  # ]
2032
2403
  # }
2033
2404
  # }
2034
2405
  ```
2035
2406
 
2036
- **BCDD::Result.config.constant_alias**
2407
+ #### **BCDD::Result.config.constant_alias** <!-- omit in toc -->
2037
2408
 
2038
2409
  ```ruby
2039
2410
  BCDD::Result.config.constant_alias.enabled?('Result')
@@ -2048,7 +2419,7 @@ BCDD::Result.config.constant_alias.options
2048
2419
  # }
2049
2420
  ```
2050
2421
 
2051
- **BCDD::Result.config.pattern_matching**
2422
+ #### **BCDD::Result.config.pattern_matching** <!-- omit in toc -->
2052
2423
 
2053
2424
  ```ruby
2054
2425
  BCDD::Result.config.pattern_matching.enabled?(:nil_as_valid_value_checking)
@@ -2059,13 +2430,13 @@ BCDD::Result.config.pattern_matching.options
2059
2430
  # :enabled=>false,
2060
2431
  # :affects=>[
2061
2432
  # "BCDD::Result::Expectations,
2062
- # "BCDD::Result::Context::Expectations"
2433
+ # "BCDD::Context::Expectations"
2063
2434
  # ]
2064
2435
  # }
2065
2436
  # }
2066
2437
  ```
2067
2438
 
2068
- **BCDD::Result.config.feature**
2439
+ #### **BCDD::Result.config.feature** <!-- omit in toc -->
2069
2440
 
2070
2441
  ```ruby
2071
2442
  BCDD::Result.config.feature.enabled?(:expectations)
@@ -2076,21 +2447,21 @@ BCDD::Result.config.feature.options
2076
2447
  # :enabled=>true,
2077
2448
  # :affects=>[
2078
2449
  # "BCDD::Result::Expectations,
2079
- # "BCDD::Result::Context::Expectations"
2450
+ # "BCDD::Context::Expectations"
2080
2451
  # ]
2081
2452
  # },
2082
- # :transitions=>{
2453
+ # event_logs=>{
2083
2454
  # :enabled=>true,
2084
2455
  # :affects=>[
2085
2456
  # "BCDD::Result",
2086
- # "BCDD::Result::Context"
2457
+ # "BCDD::Context"
2087
2458
  # ]
2088
2459
  # },
2089
2460
  # :and_then!=>{
2090
2461
  # :enabled=>false,
2091
2462
  # :affects=>[
2092
2463
  # "BCDD::Result",
2093
- # "BCDD::Result::Context"
2464
+ # "BCDD::Context"
2094
2465
  # ]
2095
2466
  # },
2096
2467
  # }
@@ -2133,7 +2504,7 @@ class PlaceOrder < Micro::Case
2133
2504
  end
2134
2505
  ```
2135
2506
 
2136
- To facilitate migration for users accustomed to the above approaches, `bcdd-result` includes the `BCDD::Result#and_then!`/`BCDD::Result::Context#and_then!` methods, which will invoke the method `call` of the given operation and expect it to return a `BCDD::Result`/`BCDD::Result::Context` object.
2507
+ To facilitate migration for users accustomed to the above approaches, `bcdd-result` includes the `BCDD::Result#and_then!`/`BCDD::Context#and_then!` methods, which will invoke the method `call` of the given operation and expect it to return a `BCDD::Result`/`BCDD::Context` object.
2137
2508
 
2138
2509
  ```ruby
2139
2510
  BCDD::Result.configure do |config|
@@ -2141,7 +2512,7 @@ BCDD::Result.configure do |config|
2141
2512
  end
2142
2513
 
2143
2514
  class PlaceOrder
2144
- include BCDD::Result::Context.mixin
2515
+ include BCDD::Context.mixin
2145
2516
 
2146
2517
  def call(**input)
2147
2518
  Given(input)
@@ -2173,11 +2544,11 @@ class PlaceOrder
2173
2544
  end
2174
2545
  ```
2175
2546
 
2176
- **In BCDD::Result::Context**
2547
+ **In BCDD::Context**
2177
2548
 
2178
2549
  ```ruby
2179
2550
  class PlaceOrder
2180
- include BCDD::Result::Context.mixin
2551
+ include BCDD::Context.mixin
2181
2552
 
2182
2553
  def call(logger:, **input)
2183
2554
  Given(input)
@@ -2231,7 +2602,7 @@ Attention: to ensure the correct behavior, do not mix `#and_then` and `#and_then
2231
2602
 
2232
2603
  #### Analysis: Why is `#and_then` the antidote/standard?
2233
2604
 
2234
- The `BCDD::Result#and_then`/`BCDD::Result::Context#and_then` methods diverge from the above approach by requiring explicit invocation and mapping of the outcomes at each process step. This approach has the following advantages:
2605
+ The `BCDD::Result#and_then`/`BCDD::Context#and_then` methods diverge from the above approach by requiring explicit invocation and mapping of the outcomes at each process step. This approach has the following advantages:
2235
2606
 
2236
2607
  - **Clarity:** The input/output relationship between the steps is apparent and highly understandable.
2237
2608
 
@@ -2241,7 +2612,7 @@ See this example to understand what your code should look like:
2241
2612
 
2242
2613
  ```ruby
2243
2614
  class PlaceOrder
2244
- include BCDD::Result::Context.mixin(config: { addon: { continue: true } })
2615
+ include BCDD::Context.mixin(config: { addon: { continue: true } })
2245
2616
 
2246
2617
  def call(**input)
2247
2618
  Given(input)
@@ -2287,7 +2658,7 @@ end
2287
2658
 
2288
2659
  ## About
2289
2660
 
2290
- [Rodrigo Serradura](https://github.com/serradura) created this project. He is the B/CDD process/method creator and has already made similar gems like the [u-case](https://github.com/serradura/u-case) and [kind](https://github.com/serradura/kind/blob/main/lib/kind/result.rb). This gem is a general-purpose abstraction/monad, but it also contains key features that serve as facilitators for adopting B/CDD in the code.
2661
+ [Rodrigo Serradura](https://github.com/serradura) created this project. He is the B/CDD process/method creator and has already made similar gems like the [u-case](https://github.com/serradura/u-case) and [kind](https://github.com/serradura/kind/blob/main/lib/kind/result.rb). This gem can be used independently, but it also contains essential features that facilitate the adoption of B/CDD in code.
2291
2662
 
2292
2663
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
2293
2664