bcdd-result 0.13.0 → 1.1.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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -4
  3. data/CHANGELOG.md +61 -21
  4. data/README.md +397 -227
  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 +6 -5
  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 +11 -11
  43. data/lib/bcdd/context.rb +115 -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
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
  <h1 align="center" id="-bcddresult">🔀 BCDD::Result</h1>
3
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
7
  <a href="https://codeclimate.com/github/B-CDD/result/maintainability"><img src="https://api.codeclimate.com/v1/badges/aa8360f8f012d7dedd62/maintainability" /></a>
8
8
  <a href="https://codeclimate.com/github/B-CDD/result/test_coverage"><img src="https://api.codeclimate.com/v1/badges/aa8360f8f012d7dedd62/test_coverage" /></a>
@@ -19,12 +19,13 @@ Furthermore, this abstraction exposes several features that will be useful to ma
19
19
 
20
20
  Use it to enable the [Railway Oriented Programming](https://fsharpforfunandprofit.com/rop/) pattern (superpower) in your code.
21
21
 
22
- - [Ruby Version](#ruby-version)
22
+ - [Supported Ruby](#supported-ruby)
23
23
  - [Installation](#installation)
24
24
  - [Usage](#usage)
25
25
  - [`BCDD::Result` *versus* `Result`](#bcddresult-versus-result)
26
26
  - [Reference](#reference)
27
- - [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)
28
29
  - [Checking types with `result.success?` or `result.failure?`](#checking-types-with-resultsuccess-or-resultfailure)
29
30
  - [Result Hooks](#result-hooks)
30
31
  - [`result.on`](#resulton)
@@ -37,9 +38,6 @@ Use it to enable the [Railway Oriented Programming](https://fsharpforfunandprofi
37
38
  - [`result.value_or`](#resultvalue_or)
38
39
  - [Result Data](#result-data)
39
40
  - [`result.data`](#resultdata)
40
- - [Pattern Matching](#pattern-matching)
41
- - [`Array`/`Find` patterns](#arrayfind-patterns)
42
- - [`Hash` patterns](#hash-patterns)
43
41
  - [Railway Oriented Programming](#railway-oriented-programming)
44
42
  - [`result.and_then`](#resultand_then)
45
43
  - [`BCDD::Result.mixin`](#bcddresultmixin)
@@ -63,17 +61,25 @@ Use it to enable the [Railway Oriented Programming](https://fsharpforfunandprofi
63
61
  - [Failure()](#failure)
64
62
  - [Pattern Matching Support](#pattern-matching-support)
65
63
  - [`BCDD::Result::Expectations.mixin` add-ons](#bcddresultexpectationsmixin-add-ons)
66
- - [`BCDD::Result::Context`](#bcddresultcontext)
64
+ - [`BCDD::Context`](#bcddcontext)
67
65
  - [Defining successes and failures](#defining-successes-and-failures)
68
- - [Constant aliases](#constant-aliases)
69
- - [`BCDD::Result::Context.mixin`](#bcddresultcontextmixin)
66
+ - [Hash methods](#hash-methods)
67
+ - [`BCDD::Context.mixin`](#bcddcontextmixin)
70
68
  - [Class example (Instance Methods)](#class-example-instance-methods-1)
71
69
  - [`and_expose`](#and_expose)
72
70
  - [Module example (Singleton Methods)](#module-example-singleton-methods-1)
73
- - [`BCDD::Result::Context::Expectations`](#bcddresultcontextexpectations)
71
+ - [`BCDD::Context::Expectations`](#bcddcontextexpectations)
74
72
  - [Mixin add-ons](#mixin-add-ons)
75
- - [`BCDD::Result.transitions`](#bcddresulttransitions)
76
- - [`ids_tree` *versus* `ids_matrix`](#ids_tree-versus-ids_matrix)
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)
77
83
  - [Configuration](#configuration)
78
84
  - [Turning on/off](#turning-onoff)
79
85
  - [Setting a `trace_id` fetcher](#setting-a-trace_id-fetcher)
@@ -93,9 +99,13 @@ Use it to enable the [Railway Oriented Programming](https://fsharpforfunandprofi
93
99
  - [License](#license)
94
100
  - [Code of Conduct](#code-of-conduct)
95
101
 
96
- ## Ruby Version
102
+ ## Supported Ruby
103
+
104
+ This library is tested against:
97
105
 
98
- `>= 2.7.0`
106
+ Version | 2.7 | 3.0 | 3.1 | 3.2 | 3.3 | Head
107
+ ---- | --- | --- | --- | --- | --- | ---
108
+ 100% Coverage | ✅ | ✅ | ✅ | ✅ | ✅ | ✅
99
109
 
100
110
  ## Installation
101
111
 
@@ -167,7 +177,7 @@ There are other aliases and configurations available. Check the [BCDD::Result.co
167
177
 
168
178
  ## Reference
169
179
 
170
- ### Result Attributes
180
+ ### Basic methods
171
181
 
172
182
  Both `BCDD::Result::Success` and `BCDD::Result::Failure` are composed of the same methods. Look at the basic ones:
173
183
 
@@ -179,20 +189,22 @@ Both `BCDD::Result::Success` and `BCDD::Result::Failure` are composed of the sam
179
189
  ################
180
190
  result = BCDD::Result::Success(:ok, my: 'value')
181
191
 
182
- result.success? # true
183
- result.failure? # false
184
- result.type # :ok
185
- 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"}
186
197
 
187
198
  ###################
188
199
  # Without a value #
189
200
  ###################
190
201
  result = BCDD::Result::Success(:yes)
191
202
 
192
- result.success? # true
193
- result.failure? # false
194
- result.type # :yes
195
- result.value # nil
203
+ result.success? # true
204
+ result.failure? # false
205
+ result.type?(:yes) # true
206
+ result.type # :yes
207
+ result.value # nil
196
208
  ```
197
209
 
198
210
  **BCDD::Result::Failure**
@@ -203,26 +215,46 @@ result.value # nil
203
215
  ################
204
216
  result = BCDD::Result::Failure(:err, 'my_value')
205
217
 
206
- result.success? # false
207
- result.failure? # true
208
- result.type # :err
209
- 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"
210
223
 
211
224
  ###################
212
225
  # Without a value #
213
226
  ###################
214
227
  result = BCDD::Result::Failure(:no)
215
228
 
216
- result.success? # false
217
- result.failure? # true
218
- result.type # :no
219
- result.value # nil
229
+ result.success? # false
230
+ result.failure? # true
231
+ result.type?(:no) # true
232
+ result.type # :no
233
+ result.value # nil
220
234
  ```
221
235
 
222
236
  In both cases, the `type` must be a symbol, and the `value` can be any kind of object.
223
237
 
224
238
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
225
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
+
226
258
  #### Checking types with `result.success?` or `result.failure?`
227
259
 
228
260
  `BCDD::Result#success?` and `BCDD::Result#failure?` are methods that allow you to check if the result is a success or a failure.
@@ -533,67 +565,6 @@ print_to_hash(**success_data) # [:success, :ok, 1]
533
565
 
534
566
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
535
567
 
536
- ### Pattern Matching
537
-
538
- The `BCDD::Result` also provides support to pattern matching.
539
-
540
- In the further examples, I will use the `Divide` lambda to exemplify its usage.
541
-
542
- ```ruby
543
- Divide = lambda do |arg1, arg2|
544
- arg1.is_a?(::Numeric) or return BCDD::Result::Failure(:invalid_arg, 'arg1 must be numeric')
545
- arg2.is_a?(::Numeric) or return BCDD::Result::Failure(:invalid_arg, 'arg2 must be numeric')
546
-
547
- return BCDD::Result::Failure(:division_by_zero, 'arg2 must not be zero') if arg2.zero?
548
-
549
- BCDD::Result::Success(:division_completed, arg1 / arg2)
550
- end
551
- ```
552
-
553
- #### `Array`/`Find` patterns
554
-
555
- ```ruby
556
- case Divide.call(4, 2)
557
- in BCDD::Result::Failure[:invalid_arg, msg] then puts msg
558
- in BCDD::Result::Failure[:division_by_zero, msg] then puts msg
559
- in BCDD::Result::Success[:division_completed, value] then puts value
560
- end
561
-
562
- # The code above will print: 2
563
-
564
- case Divide.call(4, 0)
565
- in BCDD::Result::Failure[:invalid_arg, msg] then puts msg
566
- in BCDD::Result::Failure[:division_by_zero, msg] then puts msg
567
- in BCDD::Result::Success[:division_completed, value] then puts value
568
- end
569
-
570
- # The code above will print: arg2 must not be zero
571
- ```
572
-
573
- <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
574
-
575
- #### `Hash` patterns
576
-
577
- ```ruby
578
- case Divide.call(10, 2)
579
- in { failure: { invalid_arg: msg } } then puts msg
580
- in { failure: { division_by_zero: msg } } then puts msg
581
- in { success: { division_completed: value } } then puts value
582
- end
583
-
584
- # The code above will print: 5
585
-
586
- case Divide.call('10', 2)
587
- in { failure: { invalid_arg: msg } } then puts msg
588
- in { failure: { division_by_zero: msg } } then puts msg
589
- in { success: { division_completed: value } } then puts value
590
- end
591
-
592
- # The code above will print: arg1 must be numeric
593
- ```
594
-
595
- <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
596
-
597
568
  ### Railway Oriented Programming
598
569
 
599
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.
@@ -1429,61 +1400,70 @@ result.success?(:ok)
1429
1400
 
1430
1401
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1431
1402
 
1432
- ### `BCDD::Result::Context`
1403
+ ### `BCDD::Context`
1433
1404
 
1434
- 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.
1435
1406
 
1436
- 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.
1437
1408
 
1438
1409
  #### Defining successes and failures
1439
1410
 
1440
- 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`.
1441
1412
 
1442
1413
  ```ruby
1443
- BCDD::Result::Context::Success(:ok, a: 1, b: 2)
1444
- #<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}>
1445
1416
 
1446
- BCDD::Result::Context::Failure(:err, message: 'something went wrong')
1447
- #<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"}>
1448
1419
  ```
1449
1420
 
1450
- 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.
1451
1422
 
1452
1423
  ```ruby
1453
- BCDD::Result::Context::Success(:ok, [1, 2])
1424
+ BCDD::Context::Success(:ok, [1, 2])
1454
1425
  # wrong number of arguments (given 2, expected 1) (ArgumentError)
1455
1426
 
1456
- BCDD::Result::Context::Failure(:err, { message: 'something went wrong' })
1427
+ BCDD::Context::Failure(:err, { message: 'something went wrong' })
1457
1428
  # wrong number of arguments (given 2, expected 1) (ArgumentError)
1458
1429
 
1459
1430
  #
1460
1431
  # Use ** to convert a hash to keyword arguments
1461
1432
  #
1462
- BCDD::Result::Context::Success(:ok, **{ message: 'hashes can be converted to keyword arguments' })
1463
- #<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"}>
1464
1435
  ```
1465
1436
 
1466
1437
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1467
1438
 
1468
- #### Constant aliases
1439
+ #### Hash methods
1440
+
1441
+ The `BCDD::Context` only accepts hashes as its values. Because of this, its instances have some Hash's methods to query/access the values. The available methods are:
1469
1442
 
1470
- 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.
1443
+ - `#slice` to extract only the desired keys.
1444
+ - `#[]`, `#dig`, `#fetch` to access the values.
1445
+ - `#values_at` and `#fetch_values` to get the values of the desired keys.
1471
1446
 
1472
1447
  ```ruby
1473
- BCDD::Result.configuration do |config|
1474
- config.context_alias.enable!('BCDD::Context')
1448
+ result = BCDD::Context::Success(:ok, a: 1, b: 2, c: {d: 4})
1475
1449
 
1476
- # or
1450
+ result[:a] # 1
1451
+ result.fetch(:a) # 1
1452
+ result.dig(:c, :d) # 4
1477
1453
 
1478
- config.context_alias.enable!('Context')
1479
- end
1454
+ result.slice(:a, :b) # {:a=>1, :b=>2}
1455
+
1456
+ result.values_at(:a, :b) # [1, 2]
1457
+ result.fetch_values(:a, :b) # [1, 2]
1480
1458
  ```
1481
1459
 
1460
+ These methods are available for `BCDD::Context::Success` and `BCDD::Context::Failure` instances.
1461
+
1482
1462
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1483
1463
 
1484
- #### `BCDD::Result::Context.mixin`
1464
+ #### `BCDD::Context.mixin`
1485
1465
 
1486
- As in the `BCDD::Result`, you can use the `BCDD::Result::Context.mixin` to add the `Success()` and `Failure()` methods to your classes/modules.
1466
+ As in the `BCDD::Result`, you can use the `BCDD::Context.mixin` to add the `Success()` and `Failure()` methods to your classes/modules.
1487
1467
 
1488
1468
  Let's see this feature and the data accumulation in action:
1489
1469
 
@@ -1493,7 +1473,7 @@ Let's see this feature and the data accumulation in action:
1493
1473
  require 'logger'
1494
1474
 
1495
1475
  class Divide
1496
- include BCDD::Result::Context.mixin
1476
+ include BCDD::Context.mixin
1497
1477
 
1498
1478
  def call(arg1, arg2, logger: ::Logger.new(STDOUT))
1499
1479
  validate_numbers(arg1, arg2)
@@ -1530,29 +1510,29 @@ end
1530
1510
 
1531
1511
  Divide.new.call(10, 5)
1532
1512
  # I, [2023-10-27T01:51:46.905004 #76915] INFO -- : The division result is 2
1533
- #<BCDD::Result::Context::Success type=:ok value={:number=>2}>
1513
+ #<BCDD::Context::Success type=:ok value={:number=>2}>
1534
1514
 
1535
1515
  Divide.new.call('10', 5)
1536
- #<BCDD::Result::Context::Failure type=:err value={:message=>"arg1 must be numeric"}>
1516
+ #<BCDD::Context::Failure type=:err value={:message=>"arg1 must be numeric"}>
1537
1517
 
1538
1518
  Divide.new.call(10, '5')
1539
- #<BCDD::Result::Context::Failure type=:err value={:message=>"arg2 must be numeric"}>
1519
+ #<BCDD::Context::Failure type=:err value={:message=>"arg2 must be numeric"}>
1540
1520
 
1541
1521
  Divide.new.call(10, 0)
1542
- #<BCDD::Result::Context::Failure type=:err value={:message=>"arg2 must not be zero"}>
1522
+ #<BCDD::Context::Failure type=:err value={:message=>"arg2 must not be zero"}>
1543
1523
  ```
1544
1524
 
1545
1525
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1546
1526
 
1547
1527
  ##### `and_expose`
1548
1528
 
1549
- This allows you to expose only the desired keys from the accumulated result. It can be used with any `BCDD::Result::Context` object.
1529
+ This allows you to expose only the desired keys from the accumulated result. It can be used with any `BCDD::Context` object.
1550
1530
 
1551
1531
  Let's add it to the previous example:
1552
1532
 
1553
1533
  ```ruby
1554
1534
  class Divide
1555
- include BCDD::Result::Context.mixin
1535
+ include BCDD::Context.mixin
1556
1536
 
1557
1537
  def call(arg1, arg2)
1558
1538
  validate_numbers(arg1, arg2)
@@ -1582,7 +1562,7 @@ class Divide
1582
1562
  end
1583
1563
 
1584
1564
  Divide.new.call(10, 5)
1585
- #<BCDD::Result::Context::Success type=:division_completed value={:number=>2}>
1565
+ #<BCDD::Context::Success type=:division_completed value={:number=>2}>
1586
1566
  ```
1587
1567
 
1588
1568
  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.
@@ -1591,7 +1571,7 @@ Remove the `#and_expose` call to see the difference. This will be the outcome:
1591
1571
 
1592
1572
  ```ruby
1593
1573
  Divide.new.call(10, 5)
1594
- #<BCDD::Result::Context::Success type=:ok value={:number=>2, :number1=>10, :number2=>5}>
1574
+ #<BCDD::Context::Success type=:ok value={:number=>2, :number1=>10, :number2=>5}>
1595
1575
  ```
1596
1576
 
1597
1577
  > 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`.
@@ -1600,11 +1580,11 @@ Divide.new.call(10, 5)
1600
1580
 
1601
1581
  ##### Module example (Singleton Methods)
1602
1582
 
1603
- `BCDD::Result::Context.mixin` can also produce singleton methods. Below is an example using a module (but it could be a class, too).
1583
+ `BCDD::Context.mixin` can also produce singleton methods. Below is an example using a module (but it could be a class, too).
1604
1584
 
1605
1585
  ```ruby
1606
1586
  module Divide
1607
- extend self, BCDD::Result::Context.mixin
1587
+ extend self, BCDD::Context.mixin
1608
1588
 
1609
1589
  def call(arg1, arg2)
1610
1590
  validate_numbers(arg1, arg2)
@@ -1634,29 +1614,29 @@ module Divide
1634
1614
  end
1635
1615
 
1636
1616
  Divide.call(10, 5)
1637
- #<BCDD::Result::Context::Success type=:division_completed value={:number=>2}>
1617
+ #<BCDD::Context::Success type=:division_completed value={:number=>2}>
1638
1618
 
1639
1619
  Divide.call('10', 5)
1640
- #<BCDD::Result::Context::Failure type=:err value={:message=>"arg1 must be numeric"}>
1620
+ #<BCDD::Context::Failure type=:err value={:message=>"arg1 must be numeric"}>
1641
1621
 
1642
1622
  Divide.call(10, '5')
1643
- #<BCDD::Result::Context::Failure type=:err value={:message=>"arg2 must be numeric"}>
1623
+ #<BCDD::Context::Failure type=:err value={:message=>"arg2 must be numeric"}>
1644
1624
 
1645
1625
  Divide.call(10, 0)
1646
- #<BCDD::Result::Context::Failure type=:err value={:message=>"arg2 must not be zero"}>
1626
+ #<BCDD::Context::Failure type=:err value={:message=>"arg2 must not be zero"}>
1647
1627
  ```
1648
1628
 
1649
1629
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1650
1630
 
1651
- #### `BCDD::Result::Context::Expectations`
1631
+ #### `BCDD::Context::Expectations`
1652
1632
 
1653
- The `BCDD::Result::Context::Expectations` is a `BCDD::Result::Expectations` with the `BCDD::Result::Context` features.
1633
+ The `BCDD::Context::Expectations` is a `BCDD::Result::Expectations` with the `BCDD::Context` features.
1654
1634
 
1655
1635
  This is an example using the mixin mode, but the standalone mode is also supported.
1656
1636
 
1657
1637
  ```ruby
1658
1638
  class Divide
1659
- include BCDD::Result::Context::Expectations.mixin(
1639
+ include BCDD::Context::Expectations.mixin(
1660
1640
  config: {
1661
1641
  pattern_matching: { nil_as_valid_value_checking: true }
1662
1642
  },
@@ -1680,16 +1660,16 @@ class Divide
1680
1660
  end
1681
1661
 
1682
1662
  Divide.new.call(10, 5)
1683
- #<BCDD::Result::Context::Success type=:division_completed value={:number=>2}>
1663
+ #<BCDD::Context::Success type=:division_completed value={:number=>2}>
1684
1664
  ```
1685
1665
 
1686
- 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.
1666
+ 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.
1687
1667
 
1688
1668
  Let's see this using the previous example:
1689
1669
 
1690
1670
  ```ruby
1691
1671
  Divide::Result::Success(:division_completed, number: 2)
1692
- #<BCDD::Result::Context::Success type=:division_completed value={:number=>2}>
1672
+ #<BCDD::Context::Success type=:division_completed value={:number=>2}>
1693
1673
 
1694
1674
  Divide::Result::Success(:division_completed, number: '2')
1695
1675
  # value {:number=>"2"} is not allowed for :division_completed type ({:number=>"2"}: Numeric === "2" does not return true) (BCDD::Result::Contract::Error::UnexpectedValue)
@@ -1699,7 +1679,7 @@ Divide::Result::Success(:division_completed, number: '2')
1699
1679
 
1700
1680
  #### Mixin add-ons
1701
1681
 
1702
- 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.
1682
+ 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.
1703
1683
 
1704
1684
  **given**
1705
1685
 
@@ -1707,21 +1687,21 @@ This addon is enabled by default. It will create the `Given(*value)` method. Use
1707
1687
 
1708
1688
  You can turn it off by passing `given: false` to the `config:` argument or using the `BCDD::Result.configuration`.
1709
1689
 
1710
- 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.
1690
+ 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.
1711
1691
 
1712
1692
  **continue**
1713
1693
 
1714
- 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.
1694
+ 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.
1715
1695
 
1716
1696
  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.
1717
1697
 
1718
- Let's use a mix of `BCDD::Result::Context` features to see in action with this add-on:
1698
+ Let's use a mix of `BCDD::Context` features to see in action with this add-on:
1719
1699
 
1720
1700
  ```ruby
1721
1701
  module Division
1722
1702
  require 'logger'
1723
1703
 
1724
- extend self, BCDD::Result::Context::Expectations.mixin(
1704
+ extend self, BCDD::Context::Expectations.mixin(
1725
1705
  config: {
1726
1706
  addon: { continue: true },
1727
1707
  pattern_matching: { nil_as_valid_value_checking: true }
@@ -1771,35 +1751,193 @@ end
1771
1751
 
1772
1752
  Division.call(14, 2)
1773
1753
  # I, [2023-10-27T02:01:05.812388 #77823] INFO -- : The division result is 7
1774
- #<BCDD::Result::Context::Success type=:division_completed value={:number=>7}>
1754
+ #<BCDD::Context::Success type=:division_completed value={:number=>7}>
1775
1755
 
1776
1756
  Division.call(0, 2)
1777
- ##<BCDD::Result::Context::Success type=:division_completed value={:number=>0}>
1757
+ ##<BCDD::Context::Success type=:division_completed value={:number=>0}>
1778
1758
 
1779
1759
  Division.call('14', 2)
1780
- #<BCDD::Result::Context::Failure type=:invalid_arg value={:message=>"arg1 must be numeric"}>
1760
+ #<BCDD::Context::Failure type=:invalid_arg value={:message=>"arg1 must be numeric"}>
1781
1761
 
1782
1762
  Division.call(14, '2')
1783
- #<BCDD::Result::Context::Failure type=:invalid_arg value={:message=>"arg2 must be numeric"}>
1763
+ #<BCDD::Context::Failure type=:invalid_arg value={:message=>"arg2 must be numeric"}>
1784
1764
 
1785
1765
  Division.call(14, 0)
1786
- #<BCDD::Result::Context::Failure type=:division_by_zero value={:message=>"arg2 must not be zero"}>
1766
+ #<BCDD::Context::Failure type=:division_by_zero value={:message=>"arg2 must not be zero"}>
1787
1767
  ```
1788
1768
 
1789
1769
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1790
1770
 
1791
- ## `BCDD::Result.transitions`
1771
+ ## Pattern Matching
1792
1772
 
1793
- 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.
1773
+ The `BCDD::Result` and `BCDD::Context` also provides support to pattern matching.
1794
1774
 
1795
- 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.
1775
+ ### `BCDD::Result`
1776
+
1777
+ In the further examples, I will use the `Divide` lambda to exemplify its usage.
1778
+
1779
+ ```ruby
1780
+ Divide = lambda do |arg1, arg2|
1781
+ arg1.is_a?(::Numeric) or return BCDD::Result::Failure(:invalid_arg, 'arg1 must be numeric')
1782
+ arg2.is_a?(::Numeric) or return BCDD::Result::Failure(:invalid_arg, 'arg2 must be numeric')
1783
+
1784
+ return BCDD::Result::Failure(:division_by_zero, 'arg2 must not be zero') if arg2.zero?
1785
+
1786
+ BCDD::Result::Success(:division_completed, arg1 / arg2)
1787
+ end
1788
+ ```
1789
+
1790
+ #### `Array`/`Find` patterns
1791
+
1792
+ ```ruby
1793
+ case Divide.call(4, 2)
1794
+ in BCDD::Failure[:invalid_arg, msg] then puts msg
1795
+ in BCDD::Failure[:division_by_zero, msg] then puts msg
1796
+ in BCDD::Success[:division_completed, num] then puts num
1797
+ end
1798
+
1799
+ # The code above will print: 2
1800
+
1801
+ case Divide.call(4, 0)
1802
+ in BCDD::Failure[:invalid_arg, msg] then puts msg
1803
+ in BCDD::Failure[:division_by_zero, msg] then puts msg
1804
+ in BCDD::Success[:division_completed, num] then puts num
1805
+ end
1806
+
1807
+ # The code above will print: arg2 must not be zero
1808
+ ```
1809
+
1810
+ <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1811
+
1812
+ #### `Hash` patterns
1813
+
1814
+ ```ruby
1815
+ case Divide.call(10, 2)
1816
+ in BCDD::Failure(type: :invalid_arg, value: msg) then puts msg
1817
+ in BCDD::Failure(type: :division_by_zero, value: msg) then puts msg
1818
+ in BCDD::Success(type: :division_completed, value: num) then puts num
1819
+ end
1820
+
1821
+ # The code above will print: 5
1822
+
1823
+ case Divide.call('10', 2)
1824
+ in BCDD::Failure(type: :invalid_arg, value: msg) then puts msg
1825
+ in BCDD::Failure(type: :division_by_zero, value: msg) then puts msg
1826
+ in BCDD::Success(type: :division_completed, value: num) then puts num
1827
+ end
1828
+
1829
+ # The code above will print: arg1 must be numeric
1830
+ ```
1831
+
1832
+ You can also use `BCDD::Result::Success` and `BCDD::Result::Failure` as patterns.
1833
+
1834
+ <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1835
+
1836
+
1837
+ ### `BCDD::Context`
1838
+
1839
+ In the further examples, I will use the `Divide` lambda to exemplify its usage.
1840
+
1841
+ ```ruby
1842
+ Divide = lambda do |arg1, arg2|
1843
+ arg1.is_a?(::Numeric) or return BCDD::Context::Failure(:invalid_arg, err: 'arg1 must be numeric')
1844
+ arg2.is_a?(::Numeric) or return BCDD::Context::Failure(:invalid_arg, err: 'arg2 must be numeric')
1845
+
1846
+ return BCDD::Context::Failure(:division_by_zero, err: 'arg2 must not be zero') if arg2.zero?
1847
+
1848
+ BCDD::Context::Success(:division_completed, num: arg1 / arg2)
1849
+ end
1850
+ ```
1851
+
1852
+ #### `Array`/`Find` patterns
1853
+
1854
+ ```ruby
1855
+ case Divide.call(4, 2)
1856
+ in BCDD::Failure[:invalid_arg, {msg:}] then puts msg
1857
+ in BCDD::Failure[:division_by_zero, {msg:}] then puts msg
1858
+ in BCDD::Success[:division_completed, {num:}] then puts num
1859
+ end
1860
+
1861
+ # The code above will print: 2
1862
+
1863
+ case Divide.call(4, 0)
1864
+ in BCDD::Failure[:invalid_arg, {msg:}] then puts msg
1865
+ in BCDD::Failure[:division_by_zero, {msg:}] then puts msg
1866
+ in BCDD::Success[:division_completed, {num:}] then puts num
1867
+ end
1868
+
1869
+ # The code above will print: arg2 must not be zero
1870
+ ```
1871
+
1872
+ <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1873
+
1874
+ #### `Hash` patterns
1875
+
1876
+ If you don't provide the keys :type and :value, the pattern will match the result value.
1877
+
1878
+ ```ruby
1879
+ case Divide.call(10, 2)
1880
+ in BCDD::Failure({msg:}) then puts msg
1881
+ in BCDD::Success({num:}) then puts num
1882
+ end
1883
+ ```
1884
+
1885
+ ```ruby
1886
+ case Divide.call(10, 2)
1887
+ in BCDD::Failure(type: :invalid_arg, value: {msg:}) then puts msg
1888
+ in BCDD::Failure(type: :division_by_zero, value: {msg:}) then puts msg
1889
+ in BCDD::Success(type: :division_completed, value: {num:}) then puts num
1890
+ end
1891
+
1892
+ # The code above will print: 5
1893
+
1894
+ case Divide.call('10', 2)
1895
+ in BCDD::Failure(type: :invalid_arg, value: {msg:}) then puts {msg:}
1896
+ in BCDD::Failure(type: :division_by_zero, value: {msg:}) then puts msg
1897
+ in BCDD::Success(type: :division_completed, value: {num:}) then puts num
1898
+ end
1899
+
1900
+ # The code above will print: arg1 must be numeric
1901
+ ```
1902
+
1903
+ You can also use `BCDD::Context::Success` and `BCDD::Context::Failure` as patterns.
1904
+
1905
+ <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1906
+
1907
+ ### How to pattern match without the concept of success and failure
1908
+
1909
+ 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.
1910
+
1911
+ ```ruby
1912
+ case Divide.call(10, 2)
1913
+ in BCDD::Context(:invalid_arg, {msg:}) then puts msg
1914
+ in BCDD::Context(:division_by_zero, {msg:}) then puts msg
1915
+ in BCDD::Context(:division_completed, {num:}) then puts num
1916
+ end
1917
+
1918
+ case Divide.call(10, 2)
1919
+ in BCDD::Result(:invalid_arg, msg) then puts msg
1920
+ in BCDD::Result(:division_by_zero, msg) then puts msg
1921
+ in BCDD::Result(:division_completed, num) then puts num
1922
+ end
1923
+ ```
1924
+
1925
+ The `BCDD::Result` will also work with the `BCDD::Context`, but the opposite won't.
1926
+
1927
+ <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1928
+
1929
+ ## `BCDD::Result.event_logs`
1930
+
1931
+ 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.
1932
+
1933
+ 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.
1796
1934
 
1797
1935
  ```ruby
1798
1936
  class Division
1799
1937
  include BCDD::Result.mixin(config: { addon: { continue: true } })
1800
1938
 
1801
1939
  def call(arg1, arg2)
1802
- BCDD::Result.transitions(name: 'Division', desc: 'divide two numbers') do
1940
+ BCDD::Result.event_logs(name: 'Division', desc: 'divide two numbers') do
1803
1941
  Given([arg1, arg2])
1804
1942
  .and_then(:require_numbers)
1805
1943
  .and_then(:check_for_zeros)
@@ -1835,7 +1973,7 @@ module SumDivisionsByTwo
1835
1973
  extend self, BCDD::Result.mixin
1836
1974
 
1837
1975
  def call(*numbers)
1838
- BCDD::Result.transitions(name: 'SumDivisionsByTwo') do
1976
+ BCDD::Result.event_logs(name: 'SumDivisionsByTwo') do
1839
1977
  divisions = numbers.map { |number| Division.new.call(number, 2) }
1840
1978
 
1841
1979
  if divisions.any?(&:failure?)
@@ -1854,14 +1992,17 @@ Let's see the result of the `SumDivisionsByTwo` call:
1854
1992
  result = SumDivisionsByTwo.call(20, 10)
1855
1993
  # => #<BCDD::Result::Success type=:sum value=15>
1856
1994
 
1857
- result.transitions
1995
+ result.event_logs
1858
1996
  {
1859
1997
  :version => 1,
1860
1998
  :metadata => {
1861
1999
  :duration => 0, # milliseconds
1862
2000
  :trace_id => nil, # can be set through configuration
1863
- :ids_tree => [0, [[1, []], [2, []]]],
1864
- :ids_matrix => {0 => [0, 0], 1 => [1, 1], 2 => [2, 1]}
2001
+ :ids => {
2002
+ :tree => [0, [[1, []], [2, []]]],
2003
+ :matrix => { 0 => [0, 0], 1 => [1, 1], 2 => [2, 1]},
2004
+ :level_parent => { 0 => [0, 0], 1 => [1, 0], 2 => [1, 0]}
2005
+ }
1865
2006
  },
1866
2007
  :records=> [
1867
2008
  {
@@ -1942,18 +2083,21 @@ result.transitions
1942
2083
 
1943
2084
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1944
2085
 
1945
- ### `ids_tree` *versus* `ids_matrix`
1946
-
1947
- The `:ids_matrix`. It is a simplification of the `:ids_tree` property (a graph/tree representation of the transitions ids).
2086
+ ### `metadata: {ids:}`
1948
2087
 
1949
- The matrix rows are the direct transitions from the root transition block, and the columns are the transitions nested from the direct transitions.
2088
+ The `:ids` metadata property is a hash with three properties:
2089
+ - `:tree`, a graph/tree representation of the id of each `event_logs` block.
2090
+ - `:level_parent`, a hash with the level (depth) of each block and its parent id.
2091
+ - `:matrix`, a matrix representation of the event logs ids. It is a simplification of the `:tree` property.
1950
2092
 
1951
- Use these data structures to build your own visualization of the transitions.
2093
+ Use these data structures to build your own visualization.
1952
2094
 
1953
- > Check out [Transitions Listener example](examples/single_listener/lib/single_transitions_listener.rb) to see how a listener can be used to build a visualization of the transitions, using these properties.
2095
+ > 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.
1954
2096
 
1955
2097
  ```ruby
1956
- # ids_tree #
2098
+ # tree:
2099
+ # A graph representation (array of arrays) of the each event logs block id.
2100
+ #
1957
2101
  0 # [0, [
1958
2102
  |- 1 # [1, [[2, []]]],
1959
2103
  | |- 2 # [3, []],
@@ -1964,7 +2108,24 @@ Use these data structures to build your own visualization of the transitions.
1964
2108
  | |- 7 # [8, []]
1965
2109
  |- 8 # ]]
1966
2110
 
1967
- # ids_matrix # {
2111
+ # level_parent:
2112
+ # The event logs ids are the keys, and the level (depth) and parent id the values.
2113
+ # {
2114
+ 0 # 0 => [0, 0],
2115
+ |- 1 # 1 => [1, 0],
2116
+ | |- 2 # 2 => [2, 1],
2117
+ |- 3 # 3 => [1, 0],
2118
+ |- 4 # 4 => [1, 0],
2119
+ | |- 5 # 5 => [2, 4],
2120
+ | |- 6 # 6 => [2, 4],
2121
+ | |- 7 # 7 => [3, 6],
2122
+ |- 8 # 8 => [1, 0]
2123
+ # }
2124
+
2125
+ # matrix:
2126
+ # The rows are the direct blocks from the root block,
2127
+ # and the columns are the nested blocks from the direct ones.
2128
+ # {
1968
2129
  0 | 1 | 2 | 3 | 4 # 0 => [0, 0],
1969
2130
  - | - | - | - | - # 1 => [1, 1],
1970
2131
  0 | | | | # 2 => [1, 2],
@@ -1983,78 +2144,84 @@ Use these data structures to build your own visualization of the transitions.
1983
2144
 
1984
2145
  #### Turning on/off
1985
2146
 
1986
- 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.
2147
+ 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.
1987
2148
 
1988
2149
  ```ruby
1989
2150
  BCDD::Result.configuration do |config|
1990
- config.feature.disable!(:transitions)
2151
+ config.feature.disable!(event_logs)
1991
2152
  end
1992
2153
 
1993
2154
  result = SumDivisionsByTwo.call(20, 10)
1994
2155
  # => #<BCDD::Result::Success type=:sum value=15>
1995
2156
 
1996
- result.transitions
1997
-
1998
- {:version=>1, :records=>[], :metadata=>{:duration=>0, :ids_tree=>[]}}
2157
+ result.event_logs
2158
+ {
2159
+ :version=>1,
2160
+ :records=>[],
2161
+ :metadata=>{
2162
+ :duration=>0,
2163
+ :ids=>{:tree=>[], :matrix=>{}, :level_parent=>{}}, :trace_id=>nil
2164
+ }
2165
+ }
1999
2166
  ```
2000
2167
 
2001
2168
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
2002
2169
 
2003
2170
  #### Setting a `trace_id` fetcher
2004
2171
 
2005
- You can define a lambda (arity 0) to fetch the trace_id. This lambda will be called before the first transition and will be used to set the `:trace_id` in the `:metadata` property.
2172
+ 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.
2006
2173
 
2007
2174
  Use to correlate different or the same operation (executed multiple times).
2008
2175
 
2009
2176
  ```ruby
2010
- BCDD::Result.config.transitions.trace_id = -> { Thread.current[:bcdd_result_transitions_trace_id] }
2177
+ BCDD::Result.config.event_logs.trace_id = -> { Thread.current[:bcdd_result_event_logs_trace_id] }
2011
2178
  ```
2012
2179
 
2013
2180
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
2014
2181
 
2015
2182
  #### Setting a `listener`
2016
2183
 
2017
- You can define a listener to be called during the result transitions tracking (check out [this example](examples/single_listener/lib/single_transitions_listener.rb)). It must be a class that includes `BCDD::Result::Transitions::Listener`.
2184
+ 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`.
2018
2185
 
2019
- Use it to build your additional logic on top of the transitions tracking. Examples:
2020
- - Log the transitions.
2021
- - Perform a trace of the transitions.
2022
- - Instrument the transitions (measure/report).
2023
- - Build a visualization of the transitions (Diagrams, using the `records` + `:ids_tree` and `:ids_matrix` properties).
2186
+ Use it to build your additional logic on top of the tracking. Examples:
2187
+ - Log the event logs.
2188
+ - Perform the tracing.
2189
+ - Instrument the event logs (measure/report).
2190
+ - Build a visualization (Diagrams, using the `records:` + `metadata: {ids:}` properties).
2024
2191
 
2025
- After implementing your listener, you can set it to the `BCDD::Result.config.transitions.listener=`:
2192
+ After implementing your listener, you can set it to the `BCDD::Result.config.event_logs.listener=`:
2026
2193
 
2027
2194
  ```ruby
2028
- BCDD::Result.config.transitions.listener = MyTransitionsListener
2195
+ BCDD::Result.config.event_logs.listener = MyEventLogsListener
2029
2196
  ```
2030
2197
 
2031
2198
  See the example below to understand how to implement one:
2032
2199
 
2033
2200
  ```ruby
2034
- class MyTransitionsListener
2035
- include BCDD::Result::Transitions::Listener
2201
+ class MyEventLogsListener
2202
+ include BCDD::Result::EventLogs::Listener
2036
2203
 
2037
- # A listener will be initialized before the first transition, and it is discarded after the last one.
2204
+ # A listener will be initialized before the first event logs block, and it is discarded after the last one.
2038
2205
  def initialize
2039
2206
  end
2040
2207
 
2041
- # This method will be called before each transition block.
2042
- # The parent transition block will be called first in the case of nested transition blocks.
2208
+ # This method will be called before each event logs block.
2209
+ # The parent block will be called first in the case of nested ones.
2043
2210
  #
2044
2211
  # @param scope: {:id=>1, :name=>"SomeOperation", :desc=>"Optional description"}
2045
2212
  def on_start(scope:)
2046
2213
  end
2047
2214
 
2048
- # This method will wrap all the transitions in the same block.
2049
- # It can be used to perform an instrumentation (measure/report) of the transitions.
2215
+ # This method will wrap all the event logs in the same block.
2216
+ # It can be used to perform an instrumentation (measure/report).
2050
2217
  #
2051
2218
  # @param scope: {:id=>1, :name=>"SomeOperation", :desc=>"Optional description"}
2052
- def around_transitions(scope:)
2219
+ def around_event_logs(scope:)
2053
2220
  yield
2054
2221
  end
2055
2222
 
2056
2223
  # This method will wrap each and_then call.
2057
- # It can be used to perform an instrumentation (measure/report) of the and_then calls.
2224
+ # It can be used to perform an instrumentation of the and_then calls.
2058
2225
  #
2059
2226
  # @param scope: {:id=>1, :name=>"SomeOperation", :desc=>"Optional description"}
2060
2227
  # @param and_then:
@@ -2078,29 +2245,32 @@ class MyTransitionsListener
2078
2245
  def on_record(record:)
2079
2246
  end
2080
2247
 
2081
- # This method will be called at the end of the transitions tracking.
2248
+ # This method will be called at the end of the event logs tracking.
2082
2249
  #
2083
- # @param transitions:
2250
+ # @param event_logs:
2084
2251
  # {
2085
2252
  # :version => 1,
2086
2253
  # :metadata => {
2087
2254
  # :duration => 0,
2088
2255
  # :trace_id => nil,
2089
- # :ids_tree => [0, [[1, []], [2, []]]],
2090
- # :ids_matrix => {0 => [0, 0], 1 => [1, 1], 2 => [2, 1]}
2256
+ # :ids => {
2257
+ # :tree => [0, [[1, []], [2, []]]],
2258
+ # :matrix => { 0 => [0, 0], 1 => [1, 1], 2 => [2, 1]},
2259
+ # :level_parent => { 0 => [0, 0], 1 => [1, 0], 2 => [1, 0]}
2260
+ # }
2091
2261
  # },
2092
2262
  # :records => [
2093
2263
  # # ...
2094
2264
  # ]
2095
2265
  # }
2096
- def on_finish(transitions:)
2266
+ def on_finish(event_logs:)
2097
2267
  end
2098
2268
 
2099
- # This method will be called when an exception is raised during the transitions tracking.
2269
+ # This method will be called when an exception is raised during the event logs tracking.
2100
2270
  #
2101
2271
  # @param exception: Exception
2102
- # @param transitions: Hash
2103
- def before_interruption(exception:, transitions:)
2272
+ # @param event_logs: Hash
2273
+ def before_interruption(exception:, event_logs:)
2104
2274
  end
2105
2275
  end
2106
2276
  ```
@@ -2109,15 +2279,15 @@ end
2109
2279
 
2110
2280
  #### Setting multiple `listeners`
2111
2281
 
2112
- You can use `BCDD::Result::Transitions::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.
2282
+ 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.
2113
2283
 
2114
- **Attention:** It only allows one listener to handle `around_and_then` and another `around_transitions` events.
2284
+ **Attention:** It only allows one listener to handle `around_and_then` and another `around_event_logs` records.
2115
2285
 
2116
- > The example below defines different listeners to handle `around_and_then` and `around_transitions,` but it is also possible to define a listener to handle both.
2286
+ > 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.
2117
2287
 
2118
2288
  ```ruby
2119
2289
  class AroundAndThenListener
2120
- include BCDD::Result::Transitions::Listener
2290
+ include BCDD::Result::EventLogs::Listener
2121
2291
 
2122
2292
  # It must be a static/singleton method.
2123
2293
  def self.around_and_then?
@@ -2129,21 +2299,21 @@ class AroundAndThenListener
2129
2299
  end
2130
2300
  end
2131
2301
 
2132
- class AroundTransitionsListener
2133
- include BCDD::Result::Transitions::Listener
2302
+ class AroundEventLogsListener
2303
+ include BCDD::Result::EventLogs::Listener
2134
2304
 
2135
2305
  # It must be a static/singleton method.
2136
- def self.around_transitions?
2306
+ def self.around_event_logs?
2137
2307
  true
2138
2308
  end
2139
2309
 
2140
- def around_transitions(scope:)
2310
+ def around_event_logs(scope:)
2141
2311
  #...
2142
2312
  end
2143
2313
  end
2144
2314
 
2145
- class MyTransitionsListener
2146
- include BCDD::Result::Transitions::Listener
2315
+ class MyEventLogsListener
2316
+ include BCDD::Result::EventLogs::Listener
2147
2317
  end
2148
2318
  ```
2149
2319
 
@@ -2151,20 +2321,20 @@ How to use it:
2151
2321
 
2152
2322
  ```ruby
2153
2323
  # The listeners will be called in the order they were added.
2154
- BCDD::Result.config.transitions.listener = BCDD::Result::Transitions::Listeners[
2155
- MyTransitionsListener,
2324
+ BCDD::Result.config.event_logs.listener = BCDD::Result::EventLogs::Listeners[
2325
+ MyEventLogsListener,
2156
2326
  AroundAndThenListener,
2157
- AroundTransitionsListener
2327
+ AroundEventLogsListener
2158
2328
  ]
2159
2329
  ```
2160
2330
 
2161
- > Check out [this example](examples/multiple_listeners) to see a listener to print the transitions and another to store them in the database.
2331
+ > Check out [this example](examples/multiple_listeners) to see a listener to print the event logs and another to store them in the database.
2162
2332
 
2163
2333
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
2164
2334
 
2165
2335
  ## `BCDD::Result.configuration`
2166
2336
 
2167
- 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.
2337
+ 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.
2168
2338
 
2169
2339
  > 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.
2170
2340
 
@@ -2186,13 +2356,13 @@ Let's see what each configuration in the example above does:
2186
2356
 
2187
2357
  ### `config.addon.enable!(:given, :continue)` <!-- omit in toc -->
2188
2358
 
2189
- 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).
2359
+ 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).
2190
2360
 
2191
2361
  It is also enabling the `Given()` which is already enabled by default. Link to documentation: [(1)](#add-ons) [(2)](#mixin-add-ons).
2192
2362
 
2193
2363
  ### `config.constant_alias.enable!('Result', 'BCDD::Context')` <!-- omit in toc -->
2194
2364
 
2195
- This configuration make `Result` a constant alias for `BCDD::Result`, and `BCDD::Context` a constant alias for `BCDD::Result::Context`.
2365
+ This configuration make `Result` a constant alias for `BCDD::Result`, and `BCDD::Context` a constant alias for `BCDD::Context`.
2196
2366
 
2197
2367
  Link to documentations:
2198
2368
  - [Result alias](#bcddresult-versus-result)
@@ -2200,11 +2370,11 @@ Link to documentations:
2200
2370
 
2201
2371
  ### `config.pattern_matching.disable!(:nil_as_valid_value_checking)` <!-- omit in toc -->
2202
2372
 
2203
- This configuration disables the `nil_as_valid_value_checking` for `BCDD::Result` and `BCDD::Result::Context`. Link to [documentation](#pattern-matching-support).
2373
+ This configuration disables the `nil_as_valid_value_checking` for `BCDD::Result` and `BCDD::Context`. Link to [documentation](#pattern-matching-support).
2204
2374
 
2205
2375
  ### `config.feature.disable!(:expectations)` <!-- omit in toc -->
2206
2376
 
2207
- 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.
2377
+ 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.
2208
2378
 
2209
2379
  PS: I'm using `::Rails.env.production?` to check the environment, but you can use any logic you want.
2210
2380
 
@@ -2226,18 +2396,18 @@ BCDD::Result.config.addon.options
2226
2396
  # :enabled=>false,
2227
2397
  # :affects=>[
2228
2398
  # "BCDD::Result.mixin",
2229
- # "BCDD::Result::Context.mixin",
2399
+ # "BCDD::Context.mixin",
2230
2400
  # "BCDD::Result::Expectations.mixin",
2231
- # "BCDD::Result::Context::Expectations.mixin"
2401
+ # "BCDD::Context::Expectations.mixin"
2232
2402
  # ]
2233
2403
  # },
2234
2404
  # :given=>{
2235
2405
  # :enabled=>true,
2236
2406
  # :affects=>[
2237
2407
  # "BCDD::Result.mixin",
2238
- # "BCDD::Result::Context.mixin",
2408
+ # "BCDD::Context.mixin",
2239
2409
  # "BCDD::Result::Expectations.mixin",
2240
- # "BCDD::Result::Context::Expectations.mixin"
2410
+ # "BCDD::Context::Expectations.mixin"
2241
2411
  # ]
2242
2412
  # }
2243
2413
  # }
@@ -2269,7 +2439,7 @@ BCDD::Result.config.pattern_matching.options
2269
2439
  # :enabled=>false,
2270
2440
  # :affects=>[
2271
2441
  # "BCDD::Result::Expectations,
2272
- # "BCDD::Result::Context::Expectations"
2442
+ # "BCDD::Context::Expectations"
2273
2443
  # ]
2274
2444
  # }
2275
2445
  # }
@@ -2286,21 +2456,21 @@ BCDD::Result.config.feature.options
2286
2456
  # :enabled=>true,
2287
2457
  # :affects=>[
2288
2458
  # "BCDD::Result::Expectations,
2289
- # "BCDD::Result::Context::Expectations"
2459
+ # "BCDD::Context::Expectations"
2290
2460
  # ]
2291
2461
  # },
2292
- # :transitions=>{
2462
+ # event_logs=>{
2293
2463
  # :enabled=>true,
2294
2464
  # :affects=>[
2295
2465
  # "BCDD::Result",
2296
- # "BCDD::Result::Context"
2466
+ # "BCDD::Context"
2297
2467
  # ]
2298
2468
  # },
2299
2469
  # :and_then!=>{
2300
2470
  # :enabled=>false,
2301
2471
  # :affects=>[
2302
2472
  # "BCDD::Result",
2303
- # "BCDD::Result::Context"
2473
+ # "BCDD::Context"
2304
2474
  # ]
2305
2475
  # },
2306
2476
  # }
@@ -2343,7 +2513,7 @@ class PlaceOrder < Micro::Case
2343
2513
  end
2344
2514
  ```
2345
2515
 
2346
- 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.
2516
+ 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.
2347
2517
 
2348
2518
  ```ruby
2349
2519
  BCDD::Result.configure do |config|
@@ -2351,7 +2521,7 @@ BCDD::Result.configure do |config|
2351
2521
  end
2352
2522
 
2353
2523
  class PlaceOrder
2354
- include BCDD::Result::Context.mixin
2524
+ include BCDD::Context.mixin
2355
2525
 
2356
2526
  def call(**input)
2357
2527
  Given(input)
@@ -2383,11 +2553,11 @@ class PlaceOrder
2383
2553
  end
2384
2554
  ```
2385
2555
 
2386
- **In BCDD::Result::Context**
2556
+ **In BCDD::Context**
2387
2557
 
2388
2558
  ```ruby
2389
2559
  class PlaceOrder
2390
- include BCDD::Result::Context.mixin
2560
+ include BCDD::Context.mixin
2391
2561
 
2392
2562
  def call(logger:, **input)
2393
2563
  Given(input)
@@ -2441,7 +2611,7 @@ Attention: to ensure the correct behavior, do not mix `#and_then` and `#and_then
2441
2611
 
2442
2612
  #### Analysis: Why is `#and_then` the antidote/standard?
2443
2613
 
2444
- 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:
2614
+ 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:
2445
2615
 
2446
2616
  - **Clarity:** The input/output relationship between the steps is apparent and highly understandable.
2447
2617
 
@@ -2451,7 +2621,7 @@ See this example to understand what your code should look like:
2451
2621
 
2452
2622
  ```ruby
2453
2623
  class PlaceOrder
2454
- include BCDD::Result::Context.mixin(config: { addon: { continue: true } })
2624
+ include BCDD::Context.mixin(config: { addon: { continue: true } })
2455
2625
 
2456
2626
  def call(**input)
2457
2627
  Given(input)