bcdd-result 0.13.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -4
  3. data/CHANGELOG.md +46 -17
  4. data/README.md +381 -220
  5. data/Rakefile +1 -1
  6. data/Steepfile +1 -1
  7. data/examples/multiple_listeners/Rakefile +8 -8
  8. data/examples/multiple_listeners/app/models/account/owner_creation.rb +1 -1
  9. data/examples/multiple_listeners/app/models/user/creation.rb +1 -1
  10. data/examples/multiple_listeners/app/models/user/token/creation.rb +1 -1
  11. data/examples/multiple_listeners/config/initializers/bcdd.rb +0 -2
  12. data/examples/multiple_listeners/config.rb +3 -3
  13. data/examples/multiple_listeners/db/setup.rb +2 -3
  14. data/examples/multiple_listeners/lib/bcdd/result/event_logs_record.rb +27 -0
  15. data/examples/multiple_listeners/lib/event_logs_listener/stdout.rb +60 -0
  16. data/examples/multiple_listeners/lib/runtime_breaker.rb +1 -1
  17. data/examples/service_objects/Rakefile +36 -0
  18. data/examples/service_objects/app/models/account/member.rb +10 -0
  19. data/examples/service_objects/app/models/account.rb +11 -0
  20. data/examples/service_objects/app/models/user/token.rb +7 -0
  21. data/examples/service_objects/app/models/user.rb +15 -0
  22. data/examples/service_objects/app/services/account/owner_creation.rb +47 -0
  23. data/examples/service_objects/app/services/application_service.rb +79 -0
  24. data/examples/service_objects/app/services/user/creation.rb +56 -0
  25. data/examples/service_objects/app/services/user/token/creation.rb +37 -0
  26. data/examples/service_objects/config/boot.rb +17 -0
  27. data/examples/service_objects/config/initializers/bcdd.rb +9 -0
  28. data/examples/service_objects/config.rb +20 -0
  29. data/examples/service_objects/db/setup.rb +49 -0
  30. data/examples/single_listener/Rakefile +5 -5
  31. data/examples/single_listener/app/models/account/owner_creation.rb +1 -1
  32. data/examples/single_listener/app/models/user/creation.rb +1 -1
  33. data/examples/single_listener/app/models/user/token/creation.rb +1 -1
  34. data/examples/single_listener/config/initializers/bcdd.rb +0 -2
  35. data/examples/single_listener/config.rb +1 -1
  36. data/examples/single_listener/lib/{single_transitions_listener.rb → single_event_logs_listener.rb} +32 -23
  37. data/lib/bcdd/{result/context → context}/callable_and_then.rb +5 -4
  38. data/lib/bcdd/{result/context → context}/expectations/mixin.rb +1 -1
  39. data/lib/bcdd/{result/context → context}/expectations.rb +2 -2
  40. data/lib/bcdd/context/failure.rb +9 -0
  41. data/lib/bcdd/{result/context → context}/mixin.rb +2 -2
  42. data/lib/bcdd/{result/context → context}/success.rb +6 -6
  43. data/lib/bcdd/context.rb +91 -0
  44. data/lib/bcdd/failure.rb +23 -0
  45. data/lib/bcdd/result/_self.rb +198 -0
  46. data/lib/bcdd/result/callable_and_then/caller.rb +1 -1
  47. data/lib/bcdd/result/config/switchers/addons.rb +2 -2
  48. data/lib/bcdd/result/config/switchers/constant_aliases.rb +1 -3
  49. data/lib/bcdd/result/config/switchers/features.rb +5 -5
  50. data/lib/bcdd/result/config/switchers/pattern_matching.rb +1 -1
  51. data/lib/bcdd/result/config.rb +7 -5
  52. data/lib/bcdd/result/contract/type_checker.rb +4 -0
  53. data/lib/bcdd/result/{transitions → event_logs}/config.rb +5 -3
  54. data/lib/bcdd/result/{transitions → event_logs}/listener.rb +5 -5
  55. data/lib/bcdd/result/{transitions → event_logs}/listeners.rb +17 -17
  56. data/lib/bcdd/result/{transitions → event_logs}/tracking/disabled.rb +1 -1
  57. data/lib/bcdd/result/{transitions → event_logs}/tracking/enabled.rb +15 -13
  58. data/lib/bcdd/result/{transitions → event_logs}/tracking.rb +4 -3
  59. data/lib/bcdd/result/{transitions → event_logs}/tree.rb +27 -11
  60. data/lib/bcdd/result/event_logs.rb +27 -0
  61. data/lib/bcdd/result/failure.rb +1 -3
  62. data/lib/bcdd/result/success.rb +1 -3
  63. data/lib/bcdd/result/version.rb +1 -1
  64. data/lib/bcdd/result.rb +23 -191
  65. data/lib/bcdd/success.rb +23 -0
  66. data/sig/bcdd/context.rbs +175 -0
  67. data/sig/bcdd/failure.rbs +13 -0
  68. data/sig/bcdd/result/config.rbs +1 -3
  69. data/sig/bcdd/result/context.rbs +2 -174
  70. data/sig/bcdd/result/contract.rbs +1 -0
  71. data/sig/bcdd/result/{transitions.rbs → event_logs.rbs} +19 -19
  72. data/sig/bcdd/result.rbs +13 -31
  73. data/sig/bcdd/success.rbs +13 -0
  74. metadata +41 -24
  75. data/examples/multiple_listeners/lib/bcdd/result/transitions_record.rb +0 -28
  76. data/examples/multiple_listeners/lib/transitions_listener/stdout.rb +0 -54
  77. data/lib/bcdd/result/context/failure.rb +0 -9
  78. data/lib/bcdd/result/context.rb +0 -93
  79. data/lib/bcdd/result/failure/methods.rb +0 -21
  80. data/lib/bcdd/result/success/methods.rb +0 -21
  81. data/lib/bcdd/result/transitions.rb +0 -27
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
66
  - [Constant aliases](#constant-aliases)
69
- - [`BCDD::Result::Context.mixin`](#bcddresultcontextmixin)
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,45 +1400,45 @@ 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
1439
  #### Constant aliases
1469
1440
 
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.
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.
1471
1442
 
1472
1443
  ```ruby
1473
1444
  BCDD::Result.configuration do |config|
@@ -1481,9 +1452,9 @@ end
1481
1452
 
1482
1453
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1483
1454
 
1484
- #### `BCDD::Result::Context.mixin`
1455
+ #### `BCDD::Context.mixin`
1485
1456
 
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.
1457
+ As in the `BCDD::Result`, you can use the `BCDD::Context.mixin` to add the `Success()` and `Failure()` methods to your classes/modules.
1487
1458
 
1488
1459
  Let's see this feature and the data accumulation in action:
1489
1460
 
@@ -1493,7 +1464,7 @@ Let's see this feature and the data accumulation in action:
1493
1464
  require 'logger'
1494
1465
 
1495
1466
  class Divide
1496
- include BCDD::Result::Context.mixin
1467
+ include BCDD::Context.mixin
1497
1468
 
1498
1469
  def call(arg1, arg2, logger: ::Logger.new(STDOUT))
1499
1470
  validate_numbers(arg1, arg2)
@@ -1530,29 +1501,29 @@ end
1530
1501
 
1531
1502
  Divide.new.call(10, 5)
1532
1503
  # I, [2023-10-27T01:51:46.905004 #76915] INFO -- : The division result is 2
1533
- #<BCDD::Result::Context::Success type=:ok value={:number=>2}>
1504
+ #<BCDD::Context::Success type=:ok value={:number=>2}>
1534
1505
 
1535
1506
  Divide.new.call('10', 5)
1536
- #<BCDD::Result::Context::Failure type=:err value={:message=>"arg1 must be numeric"}>
1507
+ #<BCDD::Context::Failure type=:err value={:message=>"arg1 must be numeric"}>
1537
1508
 
1538
1509
  Divide.new.call(10, '5')
1539
- #<BCDD::Result::Context::Failure type=:err value={:message=>"arg2 must be numeric"}>
1510
+ #<BCDD::Context::Failure type=:err value={:message=>"arg2 must be numeric"}>
1540
1511
 
1541
1512
  Divide.new.call(10, 0)
1542
- #<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"}>
1543
1514
  ```
1544
1515
 
1545
1516
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1546
1517
 
1547
1518
  ##### `and_expose`
1548
1519
 
1549
- 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.
1550
1521
 
1551
1522
  Let's add it to the previous example:
1552
1523
 
1553
1524
  ```ruby
1554
1525
  class Divide
1555
- include BCDD::Result::Context.mixin
1526
+ include BCDD::Context.mixin
1556
1527
 
1557
1528
  def call(arg1, arg2)
1558
1529
  validate_numbers(arg1, arg2)
@@ -1582,7 +1553,7 @@ class Divide
1582
1553
  end
1583
1554
 
1584
1555
  Divide.new.call(10, 5)
1585
- #<BCDD::Result::Context::Success type=:division_completed value={:number=>2}>
1556
+ #<BCDD::Context::Success type=:division_completed value={:number=>2}>
1586
1557
  ```
1587
1558
 
1588
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.
@@ -1591,7 +1562,7 @@ Remove the `#and_expose` call to see the difference. This will be the outcome:
1591
1562
 
1592
1563
  ```ruby
1593
1564
  Divide.new.call(10, 5)
1594
- #<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}>
1595
1566
  ```
1596
1567
 
1597
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`.
@@ -1600,11 +1571,11 @@ Divide.new.call(10, 5)
1600
1571
 
1601
1572
  ##### Module example (Singleton Methods)
1602
1573
 
1603
- `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).
1604
1575
 
1605
1576
  ```ruby
1606
1577
  module Divide
1607
- extend self, BCDD::Result::Context.mixin
1578
+ extend self, BCDD::Context.mixin
1608
1579
 
1609
1580
  def call(arg1, arg2)
1610
1581
  validate_numbers(arg1, arg2)
@@ -1634,29 +1605,29 @@ module Divide
1634
1605
  end
1635
1606
 
1636
1607
  Divide.call(10, 5)
1637
- #<BCDD::Result::Context::Success type=:division_completed value={:number=>2}>
1608
+ #<BCDD::Context::Success type=:division_completed value={:number=>2}>
1638
1609
 
1639
1610
  Divide.call('10', 5)
1640
- #<BCDD::Result::Context::Failure type=:err value={:message=>"arg1 must be numeric"}>
1611
+ #<BCDD::Context::Failure type=:err value={:message=>"arg1 must be numeric"}>
1641
1612
 
1642
1613
  Divide.call(10, '5')
1643
- #<BCDD::Result::Context::Failure type=:err value={:message=>"arg2 must be numeric"}>
1614
+ #<BCDD::Context::Failure type=:err value={:message=>"arg2 must be numeric"}>
1644
1615
 
1645
1616
  Divide.call(10, 0)
1646
- #<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"}>
1647
1618
  ```
1648
1619
 
1649
1620
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1650
1621
 
1651
- #### `BCDD::Result::Context::Expectations`
1622
+ #### `BCDD::Context::Expectations`
1652
1623
 
1653
- 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.
1654
1625
 
1655
1626
  This is an example using the mixin mode, but the standalone mode is also supported.
1656
1627
 
1657
1628
  ```ruby
1658
1629
  class Divide
1659
- include BCDD::Result::Context::Expectations.mixin(
1630
+ include BCDD::Context::Expectations.mixin(
1660
1631
  config: {
1661
1632
  pattern_matching: { nil_as_valid_value_checking: true }
1662
1633
  },
@@ -1680,16 +1651,16 @@ class Divide
1680
1651
  end
1681
1652
 
1682
1653
  Divide.new.call(10, 5)
1683
- #<BCDD::Result::Context::Success type=:division_completed value={:number=>2}>
1654
+ #<BCDD::Context::Success type=:division_completed value={:number=>2}>
1684
1655
  ```
1685
1656
 
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.
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.
1687
1658
 
1688
1659
  Let's see this using the previous example:
1689
1660
 
1690
1661
  ```ruby
1691
1662
  Divide::Result::Success(:division_completed, number: 2)
1692
- #<BCDD::Result::Context::Success type=:division_completed value={:number=>2}>
1663
+ #<BCDD::Context::Success type=:division_completed value={:number=>2}>
1693
1664
 
1694
1665
  Divide::Result::Success(:division_completed, number: '2')
1695
1666
  # 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 +1670,7 @@ Divide::Result::Success(:division_completed, number: '2')
1699
1670
 
1700
1671
  #### Mixin add-ons
1701
1672
 
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.
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.
1703
1674
 
1704
1675
  **given**
1705
1676
 
@@ -1707,21 +1678,21 @@ This addon is enabled by default. It will create the `Given(*value)` method. Use
1707
1678
 
1708
1679
  You can turn it off by passing `given: false` to the `config:` argument or using the `BCDD::Result.configuration`.
1709
1680
 
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.
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.
1711
1682
 
1712
1683
  **continue**
1713
1684
 
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.
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.
1715
1686
 
1716
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.
1717
1688
 
1718
- 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:
1719
1690
 
1720
1691
  ```ruby
1721
1692
  module Division
1722
1693
  require 'logger'
1723
1694
 
1724
- extend self, BCDD::Result::Context::Expectations.mixin(
1695
+ extend self, BCDD::Context::Expectations.mixin(
1725
1696
  config: {
1726
1697
  addon: { continue: true },
1727
1698
  pattern_matching: { nil_as_valid_value_checking: true }
@@ -1771,35 +1742,193 @@ end
1771
1742
 
1772
1743
  Division.call(14, 2)
1773
1744
  # 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}>
1745
+ #<BCDD::Context::Success type=:division_completed value={:number=>7}>
1775
1746
 
1776
1747
  Division.call(0, 2)
1777
- ##<BCDD::Result::Context::Success type=:division_completed value={:number=>0}>
1748
+ ##<BCDD::Context::Success type=:division_completed value={:number=>0}>
1778
1749
 
1779
1750
  Division.call('14', 2)
1780
- #<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"}>
1781
1752
 
1782
1753
  Division.call(14, '2')
1783
- #<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"}>
1784
1755
 
1785
1756
  Division.call(14, 0)
1786
- #<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
1787
1892
  ```
1788
1893
 
1894
+ You can also use `BCDD::Context::Success` and `BCDD::Context::Failure` as patterns.
1895
+
1789
1896
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1790
1897
 
1791
- ## `BCDD::Result.transitions`
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
1914
+ ```
1792
1915
 
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.
1916
+ The `BCDD::Result` will also work with the `BCDD::Context`, but the opposite won't.
1794
1917
 
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.
1918
+ <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1919
+
1920
+ ## `BCDD::Result.event_logs`
1921
+
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.
1923
+
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.
1796
1925
 
1797
1926
  ```ruby
1798
1927
  class Division
1799
1928
  include BCDD::Result.mixin(config: { addon: { continue: true } })
1800
1929
 
1801
1930
  def call(arg1, arg2)
1802
- BCDD::Result.transitions(name: 'Division', desc: 'divide two numbers') do
1931
+ BCDD::Result.event_logs(name: 'Division', desc: 'divide two numbers') do
1803
1932
  Given([arg1, arg2])
1804
1933
  .and_then(:require_numbers)
1805
1934
  .and_then(:check_for_zeros)
@@ -1835,7 +1964,7 @@ module SumDivisionsByTwo
1835
1964
  extend self, BCDD::Result.mixin
1836
1965
 
1837
1966
  def call(*numbers)
1838
- BCDD::Result.transitions(name: 'SumDivisionsByTwo') do
1967
+ BCDD::Result.event_logs(name: 'SumDivisionsByTwo') do
1839
1968
  divisions = numbers.map { |number| Division.new.call(number, 2) }
1840
1969
 
1841
1970
  if divisions.any?(&:failure?)
@@ -1854,14 +1983,17 @@ Let's see the result of the `SumDivisionsByTwo` call:
1854
1983
  result = SumDivisionsByTwo.call(20, 10)
1855
1984
  # => #<BCDD::Result::Success type=:sum value=15>
1856
1985
 
1857
- result.transitions
1986
+ result.event_logs
1858
1987
  {
1859
1988
  :version => 1,
1860
1989
  :metadata => {
1861
1990
  :duration => 0, # milliseconds
1862
1991
  :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]}
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
+ }
1865
1997
  },
1866
1998
  :records=> [
1867
1999
  {
@@ -1942,18 +2074,21 @@ result.transitions
1942
2074
 
1943
2075
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
1944
2076
 
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).
2077
+ ### `metadata: {ids:}`
1948
2078
 
1949
- The matrix rows are the direct transitions from the root transition block, and the columns are the transitions nested from the direct transitions.
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.
1950
2083
 
1951
- Use these data structures to build your own visualization of the transitions.
2084
+ Use these data structures to build your own visualization.
1952
2085
 
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.
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.
1954
2087
 
1955
2088
  ```ruby
1956
- # ids_tree #
2089
+ # tree:
2090
+ # A graph representation (array of arrays) of the each event logs block id.
2091
+ #
1957
2092
  0 # [0, [
1958
2093
  |- 1 # [1, [[2, []]]],
1959
2094
  | |- 2 # [3, []],
@@ -1964,7 +2099,24 @@ Use these data structures to build your own visualization of the transitions.
1964
2099
  | |- 7 # [8, []]
1965
2100
  |- 8 # ]]
1966
2101
 
1967
- # ids_matrix # {
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
+ # {
1968
2120
  0 | 1 | 2 | 3 | 4 # 0 => [0, 0],
1969
2121
  - | - | - | - | - # 1 => [1, 1],
1970
2122
  0 | | | | # 2 => [1, 2],
@@ -1983,78 +2135,84 @@ Use these data structures to build your own visualization of the transitions.
1983
2135
 
1984
2136
  #### Turning on/off
1985
2137
 
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.
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.
1987
2139
 
1988
2140
  ```ruby
1989
2141
  BCDD::Result.configuration do |config|
1990
- config.feature.disable!(:transitions)
2142
+ config.feature.disable!(event_logs)
1991
2143
  end
1992
2144
 
1993
2145
  result = SumDivisionsByTwo.call(20, 10)
1994
2146
  # => #<BCDD::Result::Success type=:sum value=15>
1995
2147
 
1996
- result.transitions
1997
-
1998
- {:version=>1, :records=>[], :metadata=>{:duration=>0, :ids_tree=>[]}}
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
+ }
1999
2157
  ```
2000
2158
 
2001
2159
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
2002
2160
 
2003
2161
  #### Setting a `trace_id` fetcher
2004
2162
 
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.
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.
2006
2164
 
2007
2165
  Use to correlate different or the same operation (executed multiple times).
2008
2166
 
2009
2167
  ```ruby
2010
- BCDD::Result.config.transitions.trace_id = -> { Thread.current[:bcdd_result_transitions_trace_id] }
2168
+ BCDD::Result.config.event_logs.trace_id = -> { Thread.current[:bcdd_result_event_logs_trace_id] }
2011
2169
  ```
2012
2170
 
2013
2171
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
2014
2172
 
2015
2173
  #### Setting a `listener`
2016
2174
 
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`.
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`.
2018
2176
 
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).
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).
2024
2182
 
2025
- After implementing your listener, you can set it to the `BCDD::Result.config.transitions.listener=`:
2183
+ After implementing your listener, you can set it to the `BCDD::Result.config.event_logs.listener=`:
2026
2184
 
2027
2185
  ```ruby
2028
- BCDD::Result.config.transitions.listener = MyTransitionsListener
2186
+ BCDD::Result.config.event_logs.listener = MyEventLogsListener
2029
2187
  ```
2030
2188
 
2031
2189
  See the example below to understand how to implement one:
2032
2190
 
2033
2191
  ```ruby
2034
- class MyTransitionsListener
2035
- include BCDD::Result::Transitions::Listener
2192
+ class MyEventLogsListener
2193
+ include BCDD::Result::EventLogs::Listener
2036
2194
 
2037
- # A listener will be initialized before the first transition, and it is discarded after the last one.
2195
+ # A listener will be initialized before the first event logs block, and it is discarded after the last one.
2038
2196
  def initialize
2039
2197
  end
2040
2198
 
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.
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.
2043
2201
  #
2044
2202
  # @param scope: {:id=>1, :name=>"SomeOperation", :desc=>"Optional description"}
2045
2203
  def on_start(scope:)
2046
2204
  end
2047
2205
 
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.
2206
+ # This method will wrap all the event logs in the same block.
2207
+ # It can be used to perform an instrumentation (measure/report).
2050
2208
  #
2051
2209
  # @param scope: {:id=>1, :name=>"SomeOperation", :desc=>"Optional description"}
2052
- def around_transitions(scope:)
2210
+ def around_event_logs(scope:)
2053
2211
  yield
2054
2212
  end
2055
2213
 
2056
2214
  # This method will wrap each and_then call.
2057
- # It can be used to perform an instrumentation (measure/report) of the and_then calls.
2215
+ # It can be used to perform an instrumentation of the and_then calls.
2058
2216
  #
2059
2217
  # @param scope: {:id=>1, :name=>"SomeOperation", :desc=>"Optional description"}
2060
2218
  # @param and_then:
@@ -2078,29 +2236,32 @@ class MyTransitionsListener
2078
2236
  def on_record(record:)
2079
2237
  end
2080
2238
 
2081
- # This method will be called at the end of the transitions tracking.
2239
+ # This method will be called at the end of the event logs tracking.
2082
2240
  #
2083
- # @param transitions:
2241
+ # @param event_logs:
2084
2242
  # {
2085
2243
  # :version => 1,
2086
2244
  # :metadata => {
2087
2245
  # :duration => 0,
2088
2246
  # :trace_id => nil,
2089
- # :ids_tree => [0, [[1, []], [2, []]]],
2090
- # :ids_matrix => {0 => [0, 0], 1 => [1, 1], 2 => [2, 1]}
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
+ # }
2091
2252
  # },
2092
2253
  # :records => [
2093
2254
  # # ...
2094
2255
  # ]
2095
2256
  # }
2096
- def on_finish(transitions:)
2257
+ def on_finish(event_logs:)
2097
2258
  end
2098
2259
 
2099
- # This method will be called when an exception is raised during the transitions tracking.
2260
+ # This method will be called when an exception is raised during the event logs tracking.
2100
2261
  #
2101
2262
  # @param exception: Exception
2102
- # @param transitions: Hash
2103
- def before_interruption(exception:, transitions:)
2263
+ # @param event_logs: Hash
2264
+ def before_interruption(exception:, event_logs:)
2104
2265
  end
2105
2266
  end
2106
2267
  ```
@@ -2109,15 +2270,15 @@ end
2109
2270
 
2110
2271
  #### Setting multiple `listeners`
2111
2272
 
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.
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.
2113
2274
 
2114
- **Attention:** It only allows one listener to handle `around_and_then` and another `around_transitions` events.
2275
+ **Attention:** It only allows one listener to handle `around_and_then` and another `around_event_logs` records.
2115
2276
 
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.
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.
2117
2278
 
2118
2279
  ```ruby
2119
2280
  class AroundAndThenListener
2120
- include BCDD::Result::Transitions::Listener
2281
+ include BCDD::Result::EventLogs::Listener
2121
2282
 
2122
2283
  # It must be a static/singleton method.
2123
2284
  def self.around_and_then?
@@ -2129,21 +2290,21 @@ class AroundAndThenListener
2129
2290
  end
2130
2291
  end
2131
2292
 
2132
- class AroundTransitionsListener
2133
- include BCDD::Result::Transitions::Listener
2293
+ class AroundEventLogsListener
2294
+ include BCDD::Result::EventLogs::Listener
2134
2295
 
2135
2296
  # It must be a static/singleton method.
2136
- def self.around_transitions?
2297
+ def self.around_event_logs?
2137
2298
  true
2138
2299
  end
2139
2300
 
2140
- def around_transitions(scope:)
2301
+ def around_event_logs(scope:)
2141
2302
  #...
2142
2303
  end
2143
2304
  end
2144
2305
 
2145
- class MyTransitionsListener
2146
- include BCDD::Result::Transitions::Listener
2306
+ class MyEventLogsListener
2307
+ include BCDD::Result::EventLogs::Listener
2147
2308
  end
2148
2309
  ```
2149
2310
 
@@ -2151,20 +2312,20 @@ How to use it:
2151
2312
 
2152
2313
  ```ruby
2153
2314
  # The listeners will be called in the order they were added.
2154
- BCDD::Result.config.transitions.listener = BCDD::Result::Transitions::Listeners[
2155
- MyTransitionsListener,
2315
+ BCDD::Result.config.event_logs.listener = BCDD::Result::EventLogs::Listeners[
2316
+ MyEventLogsListener,
2156
2317
  AroundAndThenListener,
2157
- AroundTransitionsListener
2318
+ AroundEventLogsListener
2158
2319
  ]
2159
2320
  ```
2160
2321
 
2161
- > Check out [this example](examples/multiple_listeners) to see a listener to print the transitions and another to store them in the database.
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.
2162
2323
 
2163
2324
  <p align="right"><a href="#-bcddresult">⬆️ &nbsp;back to top</a></p>
2164
2325
 
2165
2326
  ## `BCDD::Result.configuration`
2166
2327
 
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.
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.
2168
2329
 
2169
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.
2170
2331
 
@@ -2186,13 +2347,13 @@ Let's see what each configuration in the example above does:
2186
2347
 
2187
2348
  ### `config.addon.enable!(:given, :continue)` <!-- omit in toc -->
2188
2349
 
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).
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).
2190
2351
 
2191
2352
  It is also enabling the `Given()` which is already enabled by default. Link to documentation: [(1)](#add-ons) [(2)](#mixin-add-ons).
2192
2353
 
2193
2354
  ### `config.constant_alias.enable!('Result', 'BCDD::Context')` <!-- omit in toc -->
2194
2355
 
2195
- 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`.
2196
2357
 
2197
2358
  Link to documentations:
2198
2359
  - [Result alias](#bcddresult-versus-result)
@@ -2200,11 +2361,11 @@ Link to documentations:
2200
2361
 
2201
2362
  ### `config.pattern_matching.disable!(:nil_as_valid_value_checking)` <!-- omit in toc -->
2202
2363
 
2203
- 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).
2204
2365
 
2205
2366
  ### `config.feature.disable!(:expectations)` <!-- omit in toc -->
2206
2367
 
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.
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.
2208
2369
 
2209
2370
  PS: I'm using `::Rails.env.production?` to check the environment, but you can use any logic you want.
2210
2371
 
@@ -2226,18 +2387,18 @@ BCDD::Result.config.addon.options
2226
2387
  # :enabled=>false,
2227
2388
  # :affects=>[
2228
2389
  # "BCDD::Result.mixin",
2229
- # "BCDD::Result::Context.mixin",
2390
+ # "BCDD::Context.mixin",
2230
2391
  # "BCDD::Result::Expectations.mixin",
2231
- # "BCDD::Result::Context::Expectations.mixin"
2392
+ # "BCDD::Context::Expectations.mixin"
2232
2393
  # ]
2233
2394
  # },
2234
2395
  # :given=>{
2235
2396
  # :enabled=>true,
2236
2397
  # :affects=>[
2237
2398
  # "BCDD::Result.mixin",
2238
- # "BCDD::Result::Context.mixin",
2399
+ # "BCDD::Context.mixin",
2239
2400
  # "BCDD::Result::Expectations.mixin",
2240
- # "BCDD::Result::Context::Expectations.mixin"
2401
+ # "BCDD::Context::Expectations.mixin"
2241
2402
  # ]
2242
2403
  # }
2243
2404
  # }
@@ -2269,7 +2430,7 @@ BCDD::Result.config.pattern_matching.options
2269
2430
  # :enabled=>false,
2270
2431
  # :affects=>[
2271
2432
  # "BCDD::Result::Expectations,
2272
- # "BCDD::Result::Context::Expectations"
2433
+ # "BCDD::Context::Expectations"
2273
2434
  # ]
2274
2435
  # }
2275
2436
  # }
@@ -2286,21 +2447,21 @@ BCDD::Result.config.feature.options
2286
2447
  # :enabled=>true,
2287
2448
  # :affects=>[
2288
2449
  # "BCDD::Result::Expectations,
2289
- # "BCDD::Result::Context::Expectations"
2450
+ # "BCDD::Context::Expectations"
2290
2451
  # ]
2291
2452
  # },
2292
- # :transitions=>{
2453
+ # event_logs=>{
2293
2454
  # :enabled=>true,
2294
2455
  # :affects=>[
2295
2456
  # "BCDD::Result",
2296
- # "BCDD::Result::Context"
2457
+ # "BCDD::Context"
2297
2458
  # ]
2298
2459
  # },
2299
2460
  # :and_then!=>{
2300
2461
  # :enabled=>false,
2301
2462
  # :affects=>[
2302
2463
  # "BCDD::Result",
2303
- # "BCDD::Result::Context"
2464
+ # "BCDD::Context"
2304
2465
  # ]
2305
2466
  # },
2306
2467
  # }
@@ -2343,7 +2504,7 @@ class PlaceOrder < Micro::Case
2343
2504
  end
2344
2505
  ```
2345
2506
 
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.
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.
2347
2508
 
2348
2509
  ```ruby
2349
2510
  BCDD::Result.configure do |config|
@@ -2351,7 +2512,7 @@ BCDD::Result.configure do |config|
2351
2512
  end
2352
2513
 
2353
2514
  class PlaceOrder
2354
- include BCDD::Result::Context.mixin
2515
+ include BCDD::Context.mixin
2355
2516
 
2356
2517
  def call(**input)
2357
2518
  Given(input)
@@ -2383,11 +2544,11 @@ class PlaceOrder
2383
2544
  end
2384
2545
  ```
2385
2546
 
2386
- **In BCDD::Result::Context**
2547
+ **In BCDD::Context**
2387
2548
 
2388
2549
  ```ruby
2389
2550
  class PlaceOrder
2390
- include BCDD::Result::Context.mixin
2551
+ include BCDD::Context.mixin
2391
2552
 
2392
2553
  def call(logger:, **input)
2393
2554
  Given(input)
@@ -2441,7 +2602,7 @@ Attention: to ensure the correct behavior, do not mix `#and_then` and `#and_then
2441
2602
 
2442
2603
  #### Analysis: Why is `#and_then` the antidote/standard?
2443
2604
 
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:
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:
2445
2606
 
2446
2607
  - **Clarity:** The input/output relationship between the steps is apparent and highly understandable.
2447
2608
 
@@ -2451,7 +2612,7 @@ See this example to understand what your code should look like:
2451
2612
 
2452
2613
  ```ruby
2453
2614
  class PlaceOrder
2454
- include BCDD::Result::Context.mixin(config: { addon: { continue: true } })
2615
+ include BCDD::Context.mixin(config: { addon: { continue: true } })
2455
2616
 
2456
2617
  def call(**input)
2457
2618
  Given(input)