u-case 2.6.0 → 3.0.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: de7b8e442e0b578b478d9d63f05901c9023884f3f2b15a1819228af36fe7afc5
4
- data.tar.gz: 50e9128500306350a56102b93ca8bd171c75ecae24899c6157a7955e845221a3
3
+ metadata.gz: 1785653f481f4622720634abe0448ef3d41dd522473ca88e8dc75d987ddd4413
4
+ data.tar.gz: f497efd7bc60619a86a3b8bb22e15551a4b513fbe4088e92a1718bd6568ec6df
5
5
  SHA512:
6
- metadata.gz: 93fcec72232ac2d1ce479cdc2efa02d7b4eddf0d3b57e2c93346ecb6359a0f9ccba33f7851b2115c813ef53f79f9276984864f172c341be23be8c11120e933fe
7
- data.tar.gz: 9993e5cdcbe6f1e864c32a9db7f637c1cdb839bd838d1823e64b2646b704b079d9f83915af65e364abe8edd66034952202909a42833a634d04aeac11eee384bd
6
+ metadata.gz: d9d77becd6c184bd58765df5d9dbbad8cee87054e6380b259e3463117401d1107cce3549a3a9626cc97f1307766b4aaef40cc32b5a7744a288790fcae6f1ee97
7
+ data.tar.gz: b65306eb69ee9a8fe7dc39d943517aca4617181ddb2c473b6ac241edf4674634b1c7517e0f3c41ad14d243c13f7c83a782e9f6971b1212fd1c87cdb0ef14bf2d
data/.travis.sh CHANGED
@@ -1,7 +1,5 @@
1
1
  #!/bin/bash
2
2
 
3
- bundle exec rake test
4
-
5
3
  ruby_v=$(ruby -v)
6
4
 
7
5
  ACTIVEMODEL_VERSION='3.2' bundle update
@@ -16,3 +14,6 @@ if [[ $ruby_v =~ '2.5.' ]] || [[ $ruby_v =~ '2.6.' ]] || [[ $ruby_v =~ '2.7.' ]]
16
14
  ACTIVEMODEL_VERSION='6.0' bundle update
17
15
  ACTIVEMODEL_VERSION='6.0' bundle exec rake test
18
16
  fi
17
+
18
+ bundle update
19
+ bundle exec rake test
data/Gemfile CHANGED
@@ -27,9 +27,17 @@ pry_byebug_version =
27
27
  else '3.9'
28
28
  end
29
29
 
30
+ pry_version =
31
+ case RUBY_VERSION
32
+ when /\A2.2/ then '0.12.2'
33
+ when /\A2.3/ then '0.12.2'
34
+ else '0.13.1'
35
+ end
36
+
30
37
  group :development, :test do
31
38
  gem 'awesome_print', '~> 1.8'
32
39
 
40
+ gem 'pry', "~> #{pry_version}"
33
41
  gem 'pry-byebug', "~> #{pry_byebug_version}"
34
42
  end
35
43
 
data/README.md CHANGED
@@ -18,6 +18,14 @@ The main project goals are:
18
18
 
19
19
  > Note: Check out the repo https://github.com/serradura/from-fat-controllers-to-use-cases to see a Rails application that uses this gem to handle its business logic.
20
20
 
21
+ ## Documentation <!-- omit in toc -->
22
+
23
+ Version | Documentation
24
+ ---------- | -------------
25
+ Unreleased | https://github.com/serradura/u-case/blob/master/README.md
26
+ 2.6.0 | https://github.com/serradura/u-case/blob/v2.x/README.md
27
+ 1.1.0 | https://github.com/serradura/u-case/blob/v1.x/README.md
28
+
21
29
  ## Table of Contents <!-- omit in toc -->
22
30
  - [Required Ruby version](#required-ruby-version)
23
31
  - [Dependencies](#dependencies)
@@ -29,11 +37,12 @@ The main project goals are:
29
37
  - [How to define custom result types?](#how-to-define-custom-result-types)
30
38
  - [Is it possible to define a custom result type without a block?](#is-it-possible-to-define-a-custom-result-type-without-a-block)
31
39
  - [How to use the result hooks?](#how-to-use-the-result-hooks)
32
- - [Why the failure hook (without a type) exposes a different kind of data?](#why-the-failure-hook-without-a-type-exposes-a-different-kind-of-data)
40
+ - [Why the failure hook (without a type) exposes result itself?](#why-the-failure-hook-without-a-type-exposes-result-itself)
33
41
  - [What happens if a result hook was declared multiple times?](#what-happens-if-a-result-hook-was-declared-multiple-times)
34
42
  - [How to use the `Micro::Case::Result#then` method?](#how-to-use-the-microcaseresultthen-method)
43
+ - [What does happens when a `Micro::Case::Result#then` receives a block?](#what-does-happens-when-a-microcaseresultthen-receives-a-block)
35
44
  - [How to make attributes data injection using this feature?](#how-to-make-attributes-data-injection-using-this-feature)
36
- - [`Micro::Case::Flow` - How to compose use cases?](#microcaseflow---how-to-compose-use-cases)
45
+ - [`Micro::Cases::Flow` - How to compose use cases?](#microcasesflow---how-to-compose-use-cases)
37
46
  - [Is it possible to compose a use case flow with other ones?](#is-it-possible-to-compose-a-use-case-flow-with-other-ones)
38
47
  - [Is it possible a flow accumulates its input and merges each success result to use as the argument of the next use cases?](#is-it-possible-a-flow-accumulates-its-input-and-merges-each-success-result-to-use-as-the-argument-of-the-next-use-cases)
39
48
  - [How to understand what is happening during a flow execution?](#how-to-understand-what-is-happening-during-a-flow-execution)
@@ -41,17 +50,17 @@ The main project goals are:
41
50
  - [Is it possible to declare a flow which includes the use case itself?](#is-it-possible-to-declare-a-flow-which-includes-the-use-case-itself)
42
51
  - [`Micro::Case::Strict` - What is a strict use case?](#microcasestrict---what-is-a-strict-use-case)
43
52
  - [`Micro::Case::Safe` - Is there some feature to auto handle exceptions inside of a use case or flow?](#microcasesafe---is-there-some-feature-to-auto-handle-exceptions-inside-of-a-use-case-or-flow)
44
- - [`Micro::Case::Safe::Flow`](#microcasesafeflow)
53
+ - [`Micro::Cases::Safe::Flow`](#microcasessafeflow)
45
54
  - [`Micro::Case::Result#on_exception`](#microcaseresulton_exception)
46
55
  - [`u-case/with_activemodel_validation` - How to validate use case attributes?](#u-casewith_activemodel_validation---how-to-validate-use-case-attributes)
47
56
  - [If I enabled the auto validation, is it possible to disable it only in specific use case classes?](#if-i-enabled-the-auto-validation-is-it-possible-to-disable-it-only-in-specific-use-case-classes)
48
57
  - [`Kind::Validator`](#kindvalidator)
49
58
  - [Benchmarks](#benchmarks)
50
- - [`Micro::Case`](#microcase)
59
+ - [`Micro::Case` (v2.6.0)](#microcase-v260)
51
60
  - [Best overall](#best-overall)
52
61
  - [Success results](#success-results)
53
62
  - [Failure results](#failure-results)
54
- - [`Micro::Case::Flow`](#microcaseflow)
63
+ - [`Micro::Case::Flow` (v2.6.0)](#microcaseflow-v260)
55
64
  - [Comparisons](#comparisons)
56
65
  - [Examples](#examples)
57
66
  - [1️⃣ Rails App (API)](#1️⃣-rails-app-api)
@@ -107,11 +116,11 @@ class Multiply < Micro::Case
107
116
  # 2. Define the method `call!` with its business logic
108
117
  def call!
109
118
 
110
- # 3. Wrap the use case result/output using the `Success()` or `Failure()` methods
119
+ # 3. Wrap the use case result/output using the `Success(result: *)` or `Failure(result: *)` methods
111
120
  if a.is_a?(Numeric) && b.is_a?(Numeric)
112
- Success(a * b)
121
+ Success result: { number: a * b }
113
122
  else
114
- Failure { '`a` and `b` attributes must be numeric' }
123
+ Failure result: { message: '`a` and `b` attributes must be numeric' }
115
124
  end
116
125
  end
117
126
  end
@@ -125,14 +134,14 @@ end
125
134
  result = Multiply.call(a: 2, b: 2)
126
135
 
127
136
  result.success? # true
128
- result.value # 4
137
+ result.data # { number: 4 }
129
138
 
130
139
  # Failure result
131
140
 
132
141
  bad_result = Multiply.call(a: 2, b: '2')
133
142
 
134
143
  bad_result.failure? # true
135
- bad_result.value # "`a` and `b` attributes must be numeric"
144
+ bad_result.data # { message: "`a` and `b` attributes must be numeric" }
136
145
 
137
146
  #-----------------------------#
138
147
  # Calling a use case instance #
@@ -140,7 +149,7 @@ bad_result.value # "`a` and `b` attributes must be numeric"
140
149
 
141
150
  result = Multiply.new(a: 2, b: 3).call
142
151
 
143
- result.value # 6
152
+ result.value # { number: 6 }
144
153
 
145
154
  # Note:
146
155
  # ----
@@ -155,11 +164,14 @@ result.value # 6
155
164
  A `Micro::Case::Result` stores the use cases output data. These are their main methods:
156
165
  - `#success?` returns true if is a successful result.
157
166
  - `#failure?` returns true if is an unsuccessful result.
158
- - `#value` the result value itself.
167
+ - `#data` the result data itself.
159
168
  - `#type` a Symbol which gives meaning for the result, this is useful to declare different types of failures or success.
160
- - `#on_success` or `#on_failure` are hook methods that help you define the application flow.
169
+ - `#on_success` or `#on_failure` are hook methods that help you to define the application flow.
161
170
  - `#use_case` if is a failure result, the use case responsible for it will be accessible through this method. This feature is handy to handle a flow failure (this topic will be covered ahead).
162
- - `#then` allows if the current result is a success, the `then` method will allow to applying a new use case for its value.
171
+ - `#then` this method will allow applying a new use case if the current result was a success. The idea of this feature is to allow the creation of dynamic flows.
172
+ - `#[]` and `#values_at` are shortcuts to access the `#data` values.
173
+
174
+ > **Note:** for backward compatibility, you could use the `#value` method as an alias of `#data` method.
163
175
 
164
176
  [⬆️ Back to Top](#table-of-contents-)
165
177
 
@@ -174,9 +186,13 @@ class Divide < Micro::Case
174
186
  attributes :a, :b
175
187
 
176
188
  def call!
177
- invalid_attributes.empty? ? Success(a / b) : Failure(invalid_attributes)
178
- rescue => e
179
- Failure(e)
189
+ if invalid_attributes.empty?
190
+ Success result: { number: a / b }
191
+ else
192
+ Failure result: { invalid_attributes: invalid_attributes }
193
+ end
194
+ rescue => exception
195
+ Failure result: exception
180
196
  end
181
197
 
182
198
  private def invalid_attributes
@@ -189,7 +205,7 @@ end
189
205
  result = Divide.call(a: 2, b: 2)
190
206
 
191
207
  result.type # :ok
192
- result.value # 1
208
+ result.data # { number: 1 }
193
209
  result.success? # true
194
210
  result.use_case # raises `Micro::Case::Error::InvalidAccessToTheUseCaseObject: only a failure result can access its own use case`
195
211
 
@@ -198,40 +214,42 @@ result.use_case # raises `Micro::Case::Error::InvalidAccessToTheUseCaseObject: o
198
214
  bad_result = Divide.call(a: 2, b: '2')
199
215
 
200
216
  bad_result.type # :error
201
- bad_result.value # {"b"=>"2"}
217
+ bad_result.data # { invalid_attributes: { "b"=>"2" } }
202
218
  bad_result.failure? # true
203
- bad_result.use_case # #<Divide:0x0000 @__attributes={"a"=>2, "b"=>"2"}, @a=2, @b="2", @__result=#<Micro::Case::Result:0x0000 @use_case=#<Divide:0x0000 ...>, @type=:error, @value={"b"=>"2"}, @success=false>>
219
+ bad_result.use_case # #<Divide:0x0000 @__attributes={"a"=>2, "b"=>"2"}, @a=2, @b="2", @__result=#<Micro::Case::Result:0x0000 @use_case=#<Divide:0x0000 ...>, @type=:error, @value={"b"=>"2"}, @success=false>
204
220
 
205
221
  # Failure result (type == :exception)
206
222
 
207
223
  err_result = Divide.call(a: 2, b: 0)
208
224
 
209
225
  err_result.type # :exception
210
- err_result.value # <ZeroDivisionError: divided by 0>
226
+ err_result.data # { exception: <ZeroDivisionError: divided by 0> }
211
227
  err_result.failure? # true
212
- err_result.use_case # #<Divide:0x0000 @__attributes={"a"=>2, "b"=>0}, @a=2, @b=0, @__result=#<Micro::Case::Result:0x0000 @use_case=#<Divide:0x0000 ...>, @type=:exception, @value=#<ZeroDivisionError: divided by 0>, @success=false>>
228
+ err_result.use_case # #<Divide:0x0000 @__attributes={"a"=>2, "b"=>0}, @a=2, @b=0, @__result=#<Micro::Case::Result:0x0000 @use_case=#<Divide:0x0000 ...>, @type=:exception, @value=#<ZeroDivisionError: divided by 0>, @success=false>
213
229
 
214
230
  # Note:
215
231
  # ----
216
232
  # Any Exception instance which is wrapped by
217
- # the Failure() method will receive `:exception` instead of the `:error` type.
233
+ # the Failure(result: *) method will receive `:exception` instead of the `:error` type.
218
234
  ```
219
235
 
220
236
  [⬆️ Back to Top](#table-of-contents-)
221
237
 
222
238
  #### How to define custom result types?
223
239
 
224
- Answer: Use a symbol as the argument of `Success()`, `Failure()` methods and declare a block to set their values.
240
+ Answer: Use a symbol as the argument of `Success()`, `Failure()` methods and declare the `result:` keyword to set the result data.
225
241
 
226
242
  ```ruby
227
243
  class Multiply < Micro::Case
228
244
  attributes :a, :b
229
245
 
230
246
  def call!
231
- return Success(a * b) if a.is_a?(Numeric) && b.is_a?(Numeric)
232
-
233
- Failure(:invalid_data) do
234
- attributes.reject { |_, input| input.is_a?(Numeric) }
247
+ if a.is_a?(Numeric) && b.is_a?(Numeric)
248
+ Success result: { number: a * b }
249
+ else
250
+ Failure :invalid_data, result: {
251
+ attributes: attributes.reject { |_, input| input.is_a?(Numeric) }
252
+ }
235
253
  end
236
254
  end
237
255
  end
@@ -241,7 +259,7 @@ end
241
259
  result = Multiply.call(a: 3, b: 2)
242
260
 
243
261
  result.type # :ok
244
- result.value # 6
262
+ result.data # { number: 6 }
245
263
  result.success? # true
246
264
 
247
265
  # Failure result
@@ -249,7 +267,7 @@ result.success? # true
249
267
  bad_result = Multiply.call(a: 3, b: '2')
250
268
 
251
269
  bad_result.type # :invalid_data
252
- bad_result.value # {"b"=>"2"}
270
+ bad_result.data # { attributes: {"b"=>"2"} }
253
271
  bad_result.failure? # true
254
272
  ```
255
273
 
@@ -257,23 +275,25 @@ bad_result.failure? # true
257
275
 
258
276
  #### Is it possible to define a custom result type without a block?
259
277
 
260
- Answer: Yes, it is. But only for failure results!
278
+ Answer: Yes, it is possible. But this will have special behavior because the result data will be a hash with the given type as the key and true as its value.
261
279
 
262
280
  ```ruby
263
281
  class Multiply < Micro::Case
264
282
  attributes :a, :b
265
283
 
266
284
  def call!
267
- return Failure(:invalid_data) unless a.is_a?(Numeric) && b.is_a?(Numeric)
268
-
269
- Success(a * b)
285
+ if a.is_a?(Numeric) && b.is_a?(Numeric)
286
+ Success result: { number: a * b }
287
+ else
288
+ Failure(:invalid_data)
289
+ end
270
290
  end
271
291
  end
272
292
 
273
293
  result = Multiply.call(a: 2, b: '2')
274
294
 
275
295
  result.failure? # true
276
- result.value # :invalid_data
296
+ result.data # { :invalid_data => true }
277
297
  result.type # :invalid_data
278
298
  result.use_case.attributes # {"a"=>2, "b"=>"2"}
279
299
 
@@ -296,10 +316,10 @@ class Double < Micro::Case
296
316
  attribute :number
297
317
 
298
318
  def call!
299
- return Failure(:invalid) { 'the number must be a numeric value' } unless number.is_a?(Numeric)
300
- return Failure(:lte_zero) { 'the number must be greater than 0' } if number <= 0
319
+ return Failure :invalid, result: { msg: 'number must be a numeric value' } unless number.is_a?(Numeric)
320
+ return Failure :lte_zero, result: { msg: 'number must be greater than 0' } if number <= 0
301
321
 
302
- Success(number * 2)
322
+ Success result: { number: number * 2 }
303
323
  end
304
324
  end
305
325
 
@@ -309,9 +329,9 @@ end
309
329
 
310
330
  Double
311
331
  .call(number: 3)
312
- .on_success { |number| p number }
313
- .on_failure(:invalid) { |msg| raise TypeError, msg }
314
- .on_failure(:lte_zero) { |msg| raise ArgumentError, msg }
332
+ .on_success { |result| p result[:number] }
333
+ .on_failure(:invalid) { |result| raise TypeError, result[:msg] }
334
+ .on_failure(:lte_zero) { |result| raise ArgumentError, result[:msg] }
315
335
 
316
336
  # The output because it is a success:
317
337
  # 6
@@ -322,10 +342,10 @@ Double
322
342
 
323
343
  Double
324
344
  .call(number: -1)
325
- .on_success { |number| p number }
345
+ .on_success { |result| p result[:number] }
326
346
  .on_failure { |_result, use_case| puts "#{use_case.class.name} was the use case responsible for the failure" }
327
- .on_failure(:invalid) { |msg| raise TypeError, msg }
328
- .on_failure(:lte_zero) { |msg| raise ArgumentError, msg }
347
+ .on_failure(:invalid) { |result| raise TypeError, result[:msg] }
348
+ .on_failure(:lte_zero) { |result| raise ArgumentError, result[:msg] }
329
349
 
330
350
  # The outputs will be:
331
351
  #
@@ -337,7 +357,7 @@ Double
337
357
  # The use case responsible for the failure will be accessible as the second hook argument
338
358
  ```
339
359
 
340
- #### Why the failure hook (without a type) exposes a different kind of data?
360
+ #### Why the failure hook (without a type) exposes result itself?
341
361
 
342
362
  Answer: To allow you to define how to handle the program flow using some
343
363
  conditional statement (like an `if`, `case/when`).
@@ -348,9 +368,9 @@ class Double < Micro::Case
348
368
 
349
369
  def call!
350
370
  return Failure(:invalid) unless number.is_a?(Numeric)
351
- return Failure(:lte_zero) { number } if number <= 0
371
+ return Failure :lte_zero, result: attributes(:number) if number <= 0
352
372
 
353
- Success(number * 2)
373
+ Success result: { number: number * 2 }
354
374
  end
355
375
  end
356
376
 
@@ -362,32 +382,32 @@ Double
362
382
  .call(-1)
363
383
  .on_failure do |result, use_case|
364
384
  case result.type
365
- when :invalid then raise TypeError, 'the number must be a numeric value'
366
- when :lte_zero then raise ArgumentError, "the number `#{result.value}` must be greater than 0"
385
+ when :invalid then raise TypeError, "number must be a numeric value"
386
+ when :lte_zero then raise ArgumentError, "number `#{result[:number]}` must be greater than 0"
367
387
  else raise NotImplementedError
368
388
  end
369
389
  end
370
390
 
371
391
  # The output will be the exception:
372
392
  #
373
- # ArgumentError (the number `-1` must be greater than 0)
393
+ # ArgumentError (number `-1` must be greater than 0)
374
394
 
375
- #=====================================================#
376
- # Using decomposition to access result value and type #
377
- #=====================================================#
395
+ #=========================================================#
396
+ # Using decomposition to access the result data and type #
397
+ #=========================================================#
378
398
 
379
399
  # The syntax to decompose an Array can be used in methods, blocks and assigments.
380
- # If you doesn't know that, check out:
400
+ # If you doesn't know it, check out the Ruby doc:
381
401
  # https://ruby-doc.org/core-2.2.0/doc/syntax/assignment_rdoc.html#label-Array+Decomposition
382
402
  #
383
- # And the object exposed in the hook failure can be decomposed using this syntax. e.g:
403
+ # The object exposed in the hook failure is a Micro::Case::Result, and it can be decomposed using this syntax. e.g:
384
404
 
385
405
  Double
386
406
  .call(-2)
387
- .on_failure do |(value, type), use_case|
407
+ .on_failure do |(data, type), use_case|
388
408
  case type
389
- when :invalid then raise TypeError, 'the number must be a numeric value'
390
- when :lte_zero then raise ArgumentError, "the number `#{value}` must be greater than 0"
409
+ when :invalid then raise TypeError, 'number must be a numeric value'
410
+ when :lte_zero then raise ArgumentError, "number `#{data[:number]}` must be greater than 0"
391
411
  else raise NotImplementedError
392
412
  end
393
413
  end
@@ -408,26 +428,28 @@ class Double < Micro::Case
408
428
  attributes :number
409
429
 
410
430
  def call!
411
- return Failure(:invalid) { 'the number must be a numeric value' } unless number.is_a?(Numeric)
412
-
413
- Success(:computed) { number * 2 }
431
+ if number.is_a?(Numeric)
432
+ Success :computed, result: { number: number * 2 }
433
+ else
434
+ Failure :invalid, result: { msg: 'number must be a numeric value' }
435
+ end
414
436
  end
415
437
  end
416
438
 
417
439
  result = Double.call(number: 3)
418
- result.value # 6
419
- result.value * 4 # 24
440
+ result.data # { number: 6 }
441
+ result[:number] * 4 # 24
420
442
 
421
443
  accum = 0
422
444
 
423
- result.on_success { |number| accum += number }
424
- .on_success { |number| accum += number }
425
- .on_success(:computed) { |number| accum += number }
426
- .on_success(:computed) { |number| accum += number }
445
+ result.on_success { |result| accum += result[:number] }
446
+ .on_success { |result| accum += result[:number] }
447
+ .on_success(:computed) { |result| accum += result[:number] }
448
+ .on_success(:computed) { |result| accum += result[:number] }
427
449
 
428
450
  accum # 24
429
451
 
430
- result.value * 4 == accum # true
452
+ result[:number] * 4 == accum # true
431
453
  ```
432
454
 
433
455
  #### How to use the `Micro::Case::Result#then` method?
@@ -440,9 +462,9 @@ class ForbidNegativeNumber < Micro::Case
440
462
  attribute :number
441
463
 
442
464
  def call!
443
- return Success { attributes } if number >= 0
465
+ return Success result: attributes if number >= 0
444
466
 
445
- Failure { attributes }
467
+ Failure result: attributes
446
468
  end
447
469
  end
448
470
 
@@ -450,7 +472,7 @@ class Add3 < Micro::Case
450
472
  attribute :number
451
473
 
452
474
  def call!
453
- Success { { number: number + 3 } }
475
+ Success result: { number: number + 3 }
454
476
  end
455
477
  end
456
478
 
@@ -459,7 +481,7 @@ result1 =
459
481
  .call(number: -1)
460
482
  .then(Add3)
461
483
 
462
- result1.value # {'number' => -1}
484
+ result1.data # {'number' => -1}
463
485
  result1.failure? # true
464
486
 
465
487
  # ---
@@ -469,7 +491,7 @@ result2 =
469
491
  .call(number: 1)
470
492
  .then(Add3)
471
493
 
472
- result2.value # {'number' => 4}
494
+ result2.data # {'number' => 4}
473
495
  result2.success? # true
474
496
  ```
475
497
 
@@ -477,6 +499,42 @@ result2.success? # true
477
499
 
478
500
  [⬆️ Back to Top](#table-of-contents-)
479
501
 
502
+ ##### What does happens when a `Micro::Case::Result#then` receives a block?
503
+
504
+ It will yields self (a `Micro::Case::Result instance`) to the block and return the result of the block. e.g:
505
+
506
+ ```ruby
507
+ class Add < Micro::Case
508
+ attributes :a, :b
509
+
510
+ def call!
511
+ return Success result: { sum: a + b } if Kind.of.Numeric?(a, b)
512
+
513
+ Failure(:attributes_arent_numbers)
514
+ end
515
+ end
516
+
517
+ # --
518
+
519
+ success_result =
520
+ Add
521
+ .call(a: 2, b: 2)
522
+ .then { |result| result.success? ? result[:sum] : 0 }
523
+
524
+ puts success_result # 4
525
+
526
+ # --
527
+
528
+ failure_result =
529
+ Add
530
+ .call(a: 2, b: '2')
531
+ .then { |result| result.success? ? result[:sum] : 0 }
532
+
533
+ puts failure_result # 0
534
+ ```
535
+
536
+ [⬆️ Back to Top](#table-of-contents-)
537
+
480
538
  ##### How to make attributes data injection using this feature?
481
539
 
482
540
  Pass a Hash as the second argument of the `Micro::Case::Result#then` method.
@@ -491,9 +549,9 @@ Todo::FindAllForUser
491
549
 
492
550
  [⬆️ Back to Top](#table-of-contents-)
493
551
 
494
- ### `Micro::Case::Flow` - How to compose use cases?
552
+ ### `Micro::Cases::Flow` - How to compose use cases?
495
553
 
496
- In this case, this will be a **flow** (`Micro::Case::Flow`).
554
+ In this case, this will be a **flow** (`Micro::Cases::Flow`).
497
555
  The main idea of this feature is to use/reuse use cases as steps of a new use case.
498
556
 
499
557
  ```ruby
@@ -503,9 +561,9 @@ module Steps
503
561
 
504
562
  def call!
505
563
  if numbers.all? { |value| String(value) =~ /\d+/ }
506
- Success(numbers: numbers.map(&:to_i))
564
+ Success result: { numbers: numbers.map(&:to_i) }
507
565
  else
508
- Failure('numbers must contain only numeric types')
566
+ Failure result: { message: 'numbers must contain only numeric types' }
509
567
  end
510
568
  end
511
569
  end
@@ -514,7 +572,7 @@ module Steps
514
572
  attribute :numbers
515
573
 
516
574
  def call!
517
- Success(numbers: numbers.map { |number| number + 2 })
575
+ Success result: { numbers: numbers.map { |number| number + 2 } }
518
576
  end
519
577
  end
520
578
 
@@ -522,7 +580,7 @@ module Steps
522
580
  attribute :numbers
523
581
 
524
582
  def call!
525
- Success(numbers: numbers.map { |number| number * 2 })
583
+ Success result: { numbers: numbers.map { |number| number * 2 } }
526
584
  end
527
585
  end
528
586
 
@@ -530,24 +588,24 @@ module Steps
530
588
  attribute :numbers
531
589
 
532
590
  def call!
533
- Success(numbers: numbers.map { |number| number * number })
591
+ Success result: { numbers: numbers.map { |number| number * number } }
534
592
  end
535
593
  end
536
594
  end
537
595
 
538
- #---------------------------------------------#
539
- # Creating a flow using the collection syntax #
540
- #---------------------------------------------#
596
+ #-------------------------------------------#
597
+ # Creating a flow using Micro::Cases.flow() #
598
+ #-------------------------------------------#
541
599
 
542
- Add2ToAllNumbers = Micro::Case::Flow([
600
+ Add2ToAllNumbers = Micro::Cases.flow([
543
601
  Steps::ConvertTextToNumbers,
544
602
  Steps::Add2
545
603
  ])
546
604
 
547
605
  result = Add2ToAllNumbers.call(numbers: %w[1 1 2 2 3 4])
548
606
 
549
- p result.success? # true
550
- p result.value # {:numbers => [3, 3, 4, 4, 5, 6]}
607
+ result.success? # true
608
+ result.data # {:numbers => [3, 3, 4, 4, 5, 6]}
551
609
 
552
610
  #---------------------------------------------------#
553
611
  # An alternative way to create a flow using classes #
@@ -562,41 +620,14 @@ DoubleAllNumbers
562
620
  .call(numbers: %w[1 1 b 2 3 4])
563
621
  .on_failure { |message| p message } # "numbers must contain only numeric types"
564
622
 
565
- # !------------------------------------ ! #
566
- # ! Deprecated: Micro::Case::Flow mixin ! #
567
- # !-------------------------------------! #
568
-
569
- # The code below still works, but it will output a warning message:
570
- # Deprecation: Micro::Case::Flow mixin is being deprecated, please use `Micro::Case` inheritance instead.
571
-
572
- class DoubleAllNumbers
573
- include Micro::Case::Flow
574
-
575
- flow Steps::ConvertTextToNumbers,
576
- Steps::Double
577
- end
578
-
579
- # Note: This feature will be removed in the next major release (3.0)
580
-
581
- #-------------------------------------------------------------#
582
- # Another way to create a flow using the composition operator #
583
- #-------------------------------------------------------------#
584
-
585
- SquareAllNumbers =
586
- Steps::ConvertTextToNumbers >> Steps::Square
587
-
588
- SquareAllNumbers
589
- .call(numbers: %w[1 1 2 2 3 4])
590
- .on_success { |value| p value[:numbers] } # [1, 1, 4, 4, 9, 16]
591
-
592
623
  # Note:
593
624
  # ----
594
625
  # When happening a failure, the use case responsible
595
626
  # will be accessible in the result
596
627
 
597
- result = SquareAllNumbers.call(numbers: %w[1 1 b 2 3 4])
628
+ result = DoubleAllNumbers.call(numbers: %w[1 1 b 2 3 4])
598
629
 
599
- result.failure? # true
630
+ result.failure? # true
600
631
  result.use_case.is_a?(Steps::ConvertTextToNumbers) # true
601
632
 
602
633
  result.on_failure do |_message, use_case|
@@ -608,7 +639,7 @@ end
608
639
 
609
640
  #### Is it possible to compose a use case flow with other ones?
610
641
 
611
- Answer: Yes, it is.
642
+ Answer: Yes, it is possible.
612
643
 
613
644
  ```ruby
614
645
  module Steps
@@ -617,9 +648,9 @@ module Steps
617
648
 
618
649
  def call!
619
650
  if numbers.all? { |value| String(value) =~ /\d+/ }
620
- Success(numbers: numbers.map(&:to_i))
651
+ Success result: { numbers: numbers.map(&:to_i) }
621
652
  else
622
- Failure('numbers must contain only numeric types')
653
+ Failure result: { message: 'numbers must contain only numeric types' }
623
654
  end
624
655
  end
625
656
  end
@@ -628,7 +659,7 @@ module Steps
628
659
  attribute :numbers
629
660
 
630
661
  def call!
631
- Success(numbers: numbers.map { |number| number + 2 })
662
+ Success result: { numbers: numbers.map { |number| number + 2 } }
632
663
  end
633
664
  end
634
665
 
@@ -636,7 +667,7 @@ module Steps
636
667
  attribute :numbers
637
668
 
638
669
  def call!
639
- Success(numbers: numbers.map { |number| number * 2 })
670
+ Success result: { numbers: numbers.map { |number| number * 2 } }
640
671
  end
641
672
  end
642
673
 
@@ -644,20 +675,28 @@ module Steps
644
675
  attribute :numbers
645
676
 
646
677
  def call!
647
- Success(numbers: numbers.map { |number| number * number })
678
+ Success result: { numbers: numbers.map { |number| number * number } }
648
679
  end
649
680
  end
650
681
  end
651
682
 
652
- Add2ToAllNumbers = Steps::ConvertTextToNumbers >> Steps::Add2
653
- DoubleAllNumbers = Steps::ConvertTextToNumbers >> Steps::Double
654
- SquareAllNumbers = Steps::ConvertTextToNumbers >> Steps::Square
683
+ DoubleAllNumbers =
684
+ Micro::Cases.flow([Steps::ConvertTextToNumbers, Steps::Double])
655
685
 
656
- DoubleAllNumbersAndAdd2 = DoubleAllNumbers >> Steps::Add2
657
- SquareAllNumbersAndAdd2 = SquareAllNumbers >> Steps::Add2
686
+ SquareAllNumbers =
687
+ Micro::Cases.flow([Steps::ConvertTextToNumbers, Steps::Square])
688
+
689
+ DoubleAllNumbersAndAdd2 =
690
+ Micro::Cases.flow([DoubleAllNumbers, Steps::Add2])
691
+
692
+ SquareAllNumbersAndAdd2 =
693
+ Micro::Cases.flow([SquareAllNumbers, Steps::Add2])
658
694
 
659
- SquareAllNumbersAndDouble = SquareAllNumbersAndAdd2 >> DoubleAllNumbers
660
- DoubleAllNumbersAndSquareAndAdd2 = DoubleAllNumbers >> SquareAllNumbersAndAdd2
695
+ SquareAllNumbersAndDouble =
696
+ Micro::Cases.flow([SquareAllNumbersAndAdd2, DoubleAllNumbers])
697
+
698
+ DoubleAllNumbersAndSquareAndAdd2 =
699
+ Micro::Cases.flow([DoubleAllNumbers, SquareAllNumbersAndAdd2])
661
700
 
662
701
  SquareAllNumbersAndDouble
663
702
  .call(numbers: %w[1 1 2 2 3 4])
@@ -668,23 +707,23 @@ DoubleAllNumbersAndSquareAndAdd2
668
707
  .on_success { |value| p value[:numbers] } # [6, 6, 18, 18, 38, 66]
669
708
  ```
670
709
 
671
- Note: You can blend any of the [available syntaxes/approaches](#how-to-create-a-flow-which-has-reusable-steps-to-define-a-complex-use-case) to create use case flows - [examples](https://github.com/serradura/u-case/blob/master/test/micro/case/flow/blend_test.rb#L7-L34).
710
+ Note: You can blend any of the [available syntaxes/approaches](#how-to-create-a-flow-which-has-reusable-steps-to-define-a-complex-use-case) to create use case flows - [examples](https://github.com/serradura/u-case/blob/714c6b658fc6aa02617e6833ddee09eddc760f2a/test/micro/cases/flow/blend_test.rb#L5-L35).
672
711
 
673
712
  [⬆️ Back to Top](#table-of-contents-)
674
713
 
675
714
  #### Is it possible a flow accumulates its input and merges each success result to use as the argument of the next use cases?
676
715
 
677
- Answer: Yes, it is! Look at the example below to understand how the data accumulation works inside of the flow execution.
716
+ Answer: Yes, it is possible! Look at the example below to understand how the data accumulation works inside of the flow execution.
678
717
 
679
718
  ```ruby
680
719
  module Users
681
- class Find < Micro::Case
720
+ class FindByEmail < Micro::Case
682
721
  attribute :email
683
722
 
684
723
  def call!
685
724
  user = User.find_by(email: email)
686
725
 
687
- return Success { { user: user } } if user
726
+ return Success result: { user: user } if user
688
727
 
689
728
  Failure(:user_not_found)
690
729
  end
@@ -699,14 +738,14 @@ module Users
699
738
  return Failure(:user_must_be_persisted) if user.new_record?
700
739
  return Failure(:wrong_password) if user.wrong_password?(password)
701
740
 
702
- return Success { attributes(:user) }
741
+ return Success result: attributes(:user)
703
742
  end
704
743
  end
705
744
  end
706
745
 
707
746
  module Users
708
- Authenticate = Micro::Case::Flow([
709
- Find,
747
+ Authenticate = Micro::Cases.flow([
748
+ FindByEmail,
710
749
  ValidatePassword
711
750
  ])
712
751
  end
@@ -714,14 +753,14 @@ end
714
753
  Users::Authenticate
715
754
  .call(email: 'somebody@test.com', password: 'password')
716
755
  .on_success { |result| sign_in(result[:user]) }
717
- .on_failure(:wrong_password) { |result| render status: 401 }
718
- .on_failure(:user_not_found) { |result| render status: 404 }
756
+ .on_failure(:wrong_password) { render status: 401 }
757
+ .on_failure(:user_not_found) { render status: 404 }
719
758
  ```
720
759
 
721
- First, lets see the attribute of each use case:
760
+ First, lets see the attributes used by each use case:
722
761
 
723
762
  ```ruby
724
- class Users::Find < Micro::Case
763
+ class Users::FindByEmail < Micro::Case
725
764
  attribute :email
726
765
  end
727
766
 
@@ -731,14 +770,14 @@ end
731
770
  ```
732
771
 
733
772
  As you can see the `Users::ValidatePassword` expects a user as its input. So, how does it receives the user?
734
- It receives the user from the `Users::Find` success result!
773
+ It receives the user from the `Users::FindByEmail` success result!
735
774
 
736
775
  And this, is the power of use cases composition because the output
737
- of one flow will compose the input of the next use case in the flow!
776
+ of one step will compose the input of the next use case in the flow!
738
777
 
739
778
  > input **>>** process **>>** output
740
779
 
741
- > **Note:** Check out these test examples [Micro::Case::Flow](https://github.com/serradura/u-case/blob/b6d63b0db0caada67d2a6cf5cc5937000c0acf04/test/micro/case/flow/reducer_test.rb) and [Micro::Case::Safe::Flow](https://github.com/serradura/u-case/blob/b1d84b355f2b92d329e10d5d56d8012df1d32681/test/micro/case/safe/flow/reducer_test.rb) to see different use cases sharing their own data.
780
+ > **Note:** Check out these test examples [Micro::Cases::Flow](https://github.com/serradura/u-case/blob/c96a3650469da40dc9f83ff678204055b7015d01/test/micro/cases/flow/result_transitions_test.rb) and [Micro::Cases::Safe::Flow](https://github.com/serradura/u-case/blob/c96a3650469da40dc9f83ff678204055b7015d01/test/micro/cases/safe/flow/result_transitions_test.rb) to see different use cases sharing their own data.
742
781
 
743
782
  [⬆️ Back to Top](#table-of-contents-)
744
783
 
@@ -756,12 +795,12 @@ user_authenticated.transitions
756
795
  [
757
796
  {
758
797
  :use_case => {
759
- :class => Users::Find,
798
+ :class => Users::FindByEmail,
760
799
  :attributes => { :email => "rodrigo@test.com" }
761
800
  },
762
801
  :success => {
763
802
  :type => :ok,
764
- :value => {
803
+ :result => {
765
804
  :user => #<User:0x00007fb57b1c5f88 @email="rodrigo@test.com" ...>
766
805
  }
767
806
  },
@@ -777,7 +816,7 @@ user_authenticated.transitions
777
816
  },
778
817
  :success => {
779
818
  :type => :ok,
780
- :value => {
819
+ :result => {
781
820
  :user => #<User:0x00007fb57b1c5f88 @email="rodrigo@test.com" ...>
782
821
  }
783
822
  },
@@ -787,13 +826,13 @@ user_authenticated.transitions
787
826
  ```
788
827
 
789
828
  The example above shows the output generated by the `Micro::Case::Result#transitions`.
790
- With it is possible to analyze the use cases execution order and what were the given `inputs` (attributes) and `outputs` (`success.value`) in the entire execution.
829
+ With it is possible to analyze the use cases execution order and what were the given `inputs` (`[:attributes]`) and `outputs` (`[:success][:result]`) in the entire execution.
791
830
 
792
- And look up the `accessible_attributes` property, because it shows whats attributes are accessible in that flow step. For example, in the last step, you can see that the `accessible_attributes` increased because of the [flow data accumulation](#is-it-possible-a-flow-accumulates-its-input-and-merges-each-success-result-to-use-as-the-argument-of-the-next-use-cases).
831
+ And look up the `accessible_attributes` property, it shows whats attributes are accessible in that flow step. For example, in the last step, you can see that the `accessible_attributes` increased because of the [data flow accumulation](#is-it-possible-a-flow-accumulates-its-input-and-merges-each-success-result-to-use-as-the-argument-of-the-next-use-cases).
793
832
 
794
833
  > **Note:** The [`Micro::Case::Result#then`](#how-to-use-the-microcaseresultthen-method) increments the `Micro::Case::Result#transitions`.
795
834
 
796
- PS: Use the `Micro::Case::Result.disable_transition_tracking` global feature toggle to disable this feature (use once) and increase the use cases' performance.
835
+ PS: Use the `Micro::Case::Result.disable_transition_tracking` feature toggle to disable this feature (use once, because it is global) and increase the use cases' performance.
797
836
 
798
837
  ##### `Micro::Case::Result#transitions` schema
799
838
  ```ruby
@@ -806,7 +845,7 @@ PS: Use the `Micro::Case::Result.disable_transition_tracking` global feature tog
806
845
  [success:, failure:] => { # (Output)
807
846
  type: <Symbol>, # Result type. Defaults:
808
847
  # Success = :ok, Failure = :error/:exception
809
- value: <Hash> # The data returned by the use case
848
+ result: <Hash> # The data returned by the use case
810
849
  },
811
850
  accessible_attributes: <Array>, # Properties that can be accessed by the use case's attributes,
812
851
  # starting with Hash used to invoke it and which are incremented
@@ -824,7 +863,7 @@ class ConvertTextToNumber < Micro::Case
824
863
  attribute :text
825
864
 
826
865
  def call!
827
- Success { { number: text.to_i } }
866
+ Success result: { number: text.to_i }
828
867
  end
829
868
  end
830
869
 
@@ -832,7 +871,7 @@ class ConvertNumberToText < Micro::Case
832
871
  attribute :number
833
872
 
834
873
  def call!
835
- Success { { text: number.to_s } }
874
+ Success result: { text: number.to_s }
836
875
  end
837
876
  end
838
877
 
@@ -844,17 +883,17 @@ class Double < Micro::Case
844
883
  attribute :number
845
884
 
846
885
  def call!
847
- Success { { number: number * 2 } }
886
+ Success result: { number: number * 2 }
848
887
  end
849
888
  end
850
889
 
851
890
  result = Double.call(text: '4')
852
891
 
853
892
  result.success? # true
854
- result.value # "8"
893
+ result[:number] # "8"
855
894
 
856
895
  # NOTE: This feature can be used with the Micro::Case::Safe.
857
- # Checkout the test: test/micro/case/safe/flow/with_classes/using_itself_test.rb
896
+ # Checkout this test: https://github.com/serradura/u-case/blob/714c6b658fc6aa02617e6833ddee09eddc760f2a/test/micro/case/safe/with_inner_flow_test.rb
858
897
  ```
859
898
 
860
899
  [⬆️ Back to Top](#table-of-contents-)
@@ -868,7 +907,7 @@ class Double < Micro::Case::Strict
868
907
  attribute :numbers
869
908
 
870
909
  def call!
871
- Success(numbers.map { |number| number * 2 })
910
+ Success result: { numbers: numbers.map { |number| number * 2 } }
872
911
  end
873
912
  end
874
913
 
@@ -882,7 +921,7 @@ Double.call({})
882
921
 
883
922
  ### `Micro::Case::Safe` - Is there some feature to auto handle exceptions inside of a use case or flow?
884
923
 
885
- Answer: Yes, there is!
924
+ Answer: Yes, there is one!
886
925
 
887
926
  **Use cases:**
888
927
 
@@ -897,14 +936,18 @@ class Divide < Micro::Case::Safe
897
936
  attributes :a, :b
898
937
 
899
938
  def call!
900
- return Success(a / b) if a.is_a?(Integer) && b.is_a?(Integer)
901
- Failure(:not_an_integer)
939
+ if a.is_a?(Integer) && b.is_a?(Integer)
940
+ Success result: { number: a / b}
941
+ else
942
+ Failure(:not_an_integer)
943
+ end
902
944
  end
903
945
  end
904
946
 
905
947
  result = Divide.call(a: 2, b: 0)
906
- result.type == :exception # true
907
- result.value.is_a?(ZeroDivisionError) # true
948
+ result.type == :exception # true
949
+ result.data # { exception: #<ZeroDivisionError...> }
950
+ result[:exception].is_a?(ZeroDivisionError) # true
908
951
 
909
952
  result.on_failure(:exception) do |exception|
910
953
  AppLogger.error(exception.message) # E, [2019-08-21T00:05:44.195506 #9532] ERROR -- : divided by 0
@@ -925,27 +968,18 @@ end
925
968
  # Another note:
926
969
  # ------------
927
970
  # It is possible to rescue an exception even when is a safe use case.
928
- # Examples: https://github.com/serradura/u-case/blob/5a85fc238b63811a32737493dc6c59965f92491d/test/micro/case/safe_test.rb#L95-L123
971
+ # Examples: https://github.com/serradura/u-case/blob/714c6b658fc6aa02617e6833ddee09eddc760f2a/test/micro/case/safe_test.rb#L90-L118
929
972
  ```
930
973
 
931
974
  [⬆️ Back to Top](#table-of-contents-)
932
975
 
933
- #### `Micro::Case::Safe::Flow`
976
+ #### `Micro::Cases::Safe::Flow`
934
977
 
935
978
  As the safe use cases, safe flows can intercept an exception in any of its steps. These are the ways to define one:
936
979
 
937
980
  ```ruby
938
981
  module Users
939
- Create = ProcessParams & ValidateParams & Persist & SendToCRM
940
- end
941
-
942
- # Note:
943
- # The ampersand is based on the safe navigation operator. https://ruby-doc.org/core-2.6/doc/syntax/calling_methods_rdoc.html#label-Safe+navigation+operator
944
-
945
- # The alternatives to declare a safe flow are:
946
-
947
- module Users
948
- Create = Micro::Case::Safe::Flow([
982
+ Create = Micro::Cases.safe_flow([
949
983
  ProcessParams,
950
984
  ValidateParams,
951
985
  Persist,
@@ -963,23 +997,6 @@ module Users
963
997
  SendToCRM
964
998
  end
965
999
  end
966
-
967
- # !------------------------------------------ ! #
968
- # ! Deprecated: Micro::Case::Safe::Flow mixin ! #
969
- # !-------------------------------------------! #
970
-
971
- # The code below still works, but it will output a warning message:
972
- # Deprecation: Micro::Case::Flow mixin is being deprecated, please use `Micro::Case` inheritance instead.
973
-
974
- module Users
975
- class Create
976
- include Micro::Case::Safe::Flow
977
-
978
- flow ProcessParams, ValidateParams, Persist, SendToCRM
979
- end
980
- end
981
-
982
- # Note: This feature will be removed in the next major release (3.0)
983
1000
  ```
984
1001
 
985
1002
  [⬆️ Back to Top](#table-of-contents-)
@@ -999,7 +1016,7 @@ class Divide < Micro::Case::Safe
999
1016
  attributes :a, :b
1000
1017
 
1001
1018
  def call!
1002
- Success(division: a / b)
1019
+ Success result: { division: a / b }
1003
1020
  end
1004
1021
  end
1005
1022
 
@@ -1049,9 +1066,9 @@ class Multiply < Micro::Case
1049
1066
  validates :a, :b, presence: true, numericality: true
1050
1067
 
1051
1068
  def call!
1052
- return Failure(:validation_error) { {errors: self.errors} } unless valid?
1069
+ return Failure :validation_error, result: { errors: self.errors } if invalid?
1053
1070
 
1054
- Success(number: a * b)
1071
+ Success result: { number: a * b }
1055
1072
  end
1056
1073
  end
1057
1074
 
@@ -1073,7 +1090,7 @@ class Multiply < Micro::Case
1073
1090
  validates :a, :b, presence: true, numericality: true
1074
1091
 
1075
1092
  def call!
1076
- Success(number: a * b)
1093
+ Success result: { number: a * b }
1077
1094
  end
1078
1095
  end
1079
1096
 
@@ -1085,7 +1102,7 @@ end
1085
1102
 
1086
1103
  #### If I enabled the auto validation, is it possible to disable it only in specific use case classes?
1087
1104
 
1088
- Answer: Yes, it is. To do this, you only need to use the `disable_auto_validation` macro. e.g:
1105
+ Answer: Yes, it is possible. To do this, you only need to use the `disable_auto_validation` macro. e.g:
1089
1106
 
1090
1107
  ```ruby
1091
1108
  require 'u-case/with_activemodel_validation'
@@ -1098,7 +1115,7 @@ class Multiply < Micro::Case
1098
1115
  validates :a, :b, presence: true, numericality: true
1099
1116
 
1100
1117
  def call!
1101
- Success(number: a * b)
1118
+ Success result: { number: a * b }
1102
1119
  end
1103
1120
  end
1104
1121
 
@@ -1124,20 +1141,20 @@ class Todo::List::AddItem < Micro::Case
1124
1141
  validates :params, kind: ActionController::Parameters
1125
1142
 
1126
1143
  def call!
1127
- todo_params = Todo::Params.to_save(params)
1144
+ todo_params = params.require(:todo).permit(:title, :due_at)
1128
1145
 
1129
1146
  todo = user.todos.create(todo_params)
1130
1147
 
1131
- Success { { todo: todo} }
1148
+ Success result: { todo: todo }
1132
1149
  rescue ActionController::ParameterMissing => e
1133
- Failure(:parameter_missing) { { message: e.message } }
1150
+ Failure :parameter_missing, result: { message: e.message }
1134
1151
  end
1135
1152
  end
1136
1153
  ```
1137
1154
 
1138
1155
  ## Benchmarks
1139
1156
 
1140
- ### `Micro::Case`
1157
+ ### `Micro::Case` (v2.6.0)
1141
1158
 
1142
1159
  #### Best overall
1143
1160
 
@@ -1145,11 +1162,11 @@ The table below contains the average between the [Success results](#success-resu
1145
1162
 
1146
1163
  | Gem / Abstraction | Iterations per second | Comparison |
1147
1164
  | ---------------------- | --------------------: | ----------------: |
1148
- | **Micro::Case** | 116629.7 | _**The Fastest**_ |
1149
- | Dry::Monads | 101796.3 | 1.14x slower |
1150
- | Interactor | 21230.5 | 5.49x slower |
1151
- | Trailblazer::Operation | 16466.6 | 7.08x slower |
1152
- | Dry::Transaction | 5069.5 | 23.00x slower |
1165
+ | **Micro::Case** | 105124.3 | _**The Fastest**_ |
1166
+ | Dry::Monads | 103290.1 | 0.02x slower |
1167
+ | Interactor | 21342.3 | 4.93x slower |
1168
+ | Trailblazer::Operation | 14652.7 | 7.17x slower |
1169
+ | Dry::Transaction | 5310.3 | 19.80x slower |
1153
1170
 
1154
1171
  ---
1155
1172
 
@@ -1157,44 +1174,43 @@ The table below contains the average between the [Success results](#success-resu
1157
1174
 
1158
1175
  | Gem / Abstraction | Iterations per second | Comparison |
1159
1176
  | ----------------- | --------------------: | ----------------: |
1160
- | Dry::Monads | 139352.5 | _**The Fastest**_ |
1161
- | **Micro::Case** | 124749.4 | 1.12x slower |
1162
- | Interactor | 28974.4 | 4.81x slower |
1163
- | Trailblazer::Operation | 17275.6 | 8.07x slower |
1164
- | Dry::Transaction | 5571.7 | 25.01x slower |
1177
+ | Dry::Monads | 134801.0 | _**The Fastest**_ |
1178
+ | **Micro::Case** | 105909.2 | 1.27x slower |
1179
+ | Interactor | 29458.2 | 4.58x slower |
1180
+ | Trailblazer::Operation | 14714.9 | 9.16x slower |
1181
+ | Dry::Transaction | 5642.6 | 28.89x slower |
1165
1182
 
1166
1183
  <details>
1167
1184
  <summary>Show the full <a href="https://github.com/evanphx/benchmark-ips">benchmark/ips</a> results.</summary>
1168
1185
 
1169
- ```ruby
1170
- # Warming up --------------------------------------
1171
- # Interactor 2.865k i/100ms
1172
- # Trailblazer::Operation
1173
- # 1.686k i/100ms
1174
- # Dry::Monads 13.389k i/100ms
1175
- # Dry::Transaction 551.000 i/100ms
1176
- # Micro::Case 11.984k i/100ms
1177
- # Micro::Case::Strict 9.102k i/100ms
1178
- # Micro::Case::Safe 11.747k i/100ms
1179
- # Calculating -------------------------------------
1180
- # Interactor 28.974k2.7%) i/s - 146.115k in 5.046703s
1181
- # Trailblazer::Operation
1182
- # 17.276k1.8%) i/s - 87.672k in 5.076609s
1183
- # Dry::Monads 139.353k (± 2.5%) i/s - 709.617k in 5.095599s
1184
- # Dry::Transaction 5.572k3.6%) i/s - 28.101k in 5.050376s
1185
- # Micro::Case 124.749k (± 1.9%) i/s - 635.152k in 5.093310s
1186
- # Micro::Case::Strict 93.417k4.8%) i/s - 473.304k in 5.081341s
1187
- # Micro::Case::Safe 120.607k (± 3.2%) i/s - 610.844k in 5.070394s
1188
-
1189
- # Comparison:
1190
- # Dry::Monads: 139352.5 i/s
1191
- # Micro::Case: 124749.4 i/s - 1.12x slower
1192
- # Micro::Case::Safe: 120607.3 i/s - 1.16x slower
1193
- # Micro::Case::Strict: 93417.3 i/s - 1.49x slower
1194
- # Interactor: 28974.4 i/s - 4.81x slower
1195
- # Trailblazer::Operation: 17275.6 i/s - 8.07x slower
1196
- # Dry::Transaction: 5571.7 i/s - 25.01x slower
1197
- ```
1186
+ ```ruby
1187
+ # Warming up --------------------------------------
1188
+ # Interactor 2.897k i/100ms
1189
+ # Trailblazer::Operation 1.494k i/100ms
1190
+ # Dry::Monads 13.854k i/100ms
1191
+ # Dry::Transaction 561.000 i/100ms
1192
+ # Micro::Case 10.523k i/100ms
1193
+ # Micro::Case::Strict 7.982k i/100ms
1194
+ # Micro::Case::Safe 10.568k i/100ms
1195
+
1196
+ # Calculating -------------------------------------
1197
+ # Interactor 29.458k3.4%) i/s - 147.747k in 5.021405s
1198
+ # Trailblazer::Operation 14.715k (± 1.8%) i/s - 74.700k in 5.078128s
1199
+ # Dry::Monads 134.801k8.7%) i/s - 678.846k in 5.088739s
1200
+ # Dry::Transaction 5.643k (± 2.1%) i/s - 28.611k in 5.072969s
1201
+ # Micro::Case 105.909k2.4%) i/s - 536.673k in 5.070329s
1202
+ # Micro::Case::Strict 84.234k (± 1.5%) i/s - 423.046k in 5.023447s
1203
+ # Micro::Case::Safe 105.725k1.9%) i/s - 538.968k in 5.099817s
1204
+
1205
+ # Comparison:
1206
+ # Dry::Monads: 134801.0 i/s
1207
+ # Micro::Case: 105909.2 i/s - 1.27x (± 0.00) slower
1208
+ # Micro::Case::Safe: 105725.0 i/s - 1.28x (± 0.00) slower
1209
+ # Micro::Case::Strict: 84234.4 i/s - 1.60x (± 0.00) slower
1210
+ # Interactor: 29458.2 i/s - 4.58x (± 0.00) slower
1211
+ # Trailblazer::Operation: 14714.9 i/s - 9.16x (± 0.00) slower
1212
+ # Dry::Transaction: 5642.6 i/s - 23.89x (± 0.00) slower
1213
+ ```
1198
1214
  </details>
1199
1215
 
1200
1216
  https://github.com/serradura/u-case/blob/master/benchmarks/use_case/with_success_result.rb
@@ -1203,100 +1219,98 @@ https://github.com/serradura/u-case/blob/master/benchmarks/use_case/with_success
1203
1219
 
1204
1220
  | Gem / Abstraction | Iterations per second | Comparison |
1205
1221
  | ----------------- | --------------------: | ----------------: |
1206
- | **Micro::Case** | 108510.0 | _**The Fastest**_ |
1207
- | Dry::Monads | 64240.1 | 1.69x slower |
1208
- | Trailblazer::Operation | 15657.7 | 6.93x slower |
1209
- | Interactor | 13486.7 | 8.05x slower |
1210
- | Dry::Transaction | 4567.3 | 23.76x slower |
1222
+ | **Micro::Case** | 104339.4 | _**The Fastest**_ |
1223
+ | Dry::Monads | 71779.2 | 1.45x slower |
1224
+ | Trailblazer::Operation | 14590.6 | 7.15x slower |
1225
+ | Interactor | 13226.5 | 7.89x slower |
1226
+ | Dry::Transaction | 4978.1 | 20.96x slower |
1211
1227
 
1212
1228
  <details>
1213
1229
  <summary>Show the full <a href="https://github.com/evanphx/benchmark-ips">benchmark/ips</a> results.</summary>
1214
1230
 
1215
- ```ruby
1216
- # Warming up --------------------------------------
1217
- # Interactor 1.331k i/100ms
1218
- # Trailblazer::Operation
1219
- # 1.544k i/100ms
1220
- # Dry::Monads 6.343k i/100ms
1221
- # Dry::Transaction 456.000 i/100ms
1222
- # Micro::Case 10.429k i/100ms
1223
- # Micro::Case::Strict 8.109k i/100ms
1224
- # Micro::Case::Safe 10.280k i/100ms
1225
- # Calculating -------------------------------------
1226
- # Interactor 13.487k1.9%) i/s - 67.881k in 5.035059s
1227
- # Trailblazer::Operation
1228
- # 15.658k1.6%) i/s - 78.744k in 5.030427s
1229
- # Dry::Monads 64.240k1.8%) i/s - 323.493k in 5.037461s
1230
- # Dry::Transaction 4.567k (± 1.3%) i/s - 23.256k in 5.092699s
1231
- # Micro::Case 108.510k (± 2.3%) i/s - 542.308k in 5.000605s
1232
- # Micro::Case::Strict 83.527k (± 1.4%) i/s - 421.668k in 5.049245s
1233
- # Micro::Case::Safe 105.641k (± 3.7%) i/s - 534.560k in 5.067836s
1234
-
1235
- # Comparison:
1236
- # Micro::Case: 108510.0 i/s
1237
- # Micro::Case::Safe: 105640.6 i/s - same-ish: difference falls within error
1238
- # Micro::Case::Strict: 83526.8 i/s - 1.30x slower
1239
- # Dry::Monads: 64240.1 i/s - 1.69x slower
1240
- # Trailblazer::Operation: 15657.7 i/s - 6.93x slower
1241
- # Interactor: 13486.7 i/s - 8.05x slower
1242
- # Dry::Transaction: 4567.3 i/s - 23.76x slower
1243
- ```
1231
+ ```ruby
1232
+ # Warming up --------------------------------------
1233
+ # Interactor 1.339k i/100ms
1234
+ # Trailblazer::Operation 1.393k i/100ms
1235
+ # Dry::Monads 7.208k i/100ms
1236
+ # Dry::Transaction 423.000 i/100ms
1237
+ # Micro::Case 9.620k i/100ms
1238
+ # Micro::Case::Strict 8.238k i/100ms
1239
+ # Micro::Case::Safe 9.906k i/100ms
1240
+
1241
+ # Calculating -------------------------------------
1242
+ # Interactor 13.227k3.3%) i/s - 66.950k in 5.067145s
1243
+ # Trailblazer::Operation 14.591k (± 4.0%) i/s - 73.829k in 5.069162s
1244
+ # Dry::Monads 71.779k2.5%) i/s - 360.400k in 5.024294s
1245
+ # Dry::Transaction 4.978k3.3%) i/s - 24.957k in 5.019153s
1246
+ # Micro::Case 103.957k (± 1.8%) i/s - 529.100k in 5.091221s
1247
+ # Micro::Case::Strict 83.094k (± 2.0%) i/s - 420.138k in 5.058233s
1248
+ # Micro::Case::Safe 104.339k (± 1.7%) i/s - 525.018k in 5.033381s
1249
+
1250
+ # Comparison:
1251
+ # Micro::Case::Safe: 104339.4 i/s
1252
+ # Micro::Case: 103957.2 i/s - same-ish: difference falls within error
1253
+ # Micro::Case::Strict: 83094.5 i/s - 1.26x (± 0.00) slower
1254
+ # Dry::Monads: 71779.2 i/s - 1.45x (± 0.00) slower
1255
+ # Trailblazer::Operation: 14590.6 i/s - 7.15x (± 0.00) slower
1256
+ # Interactor: 13226.5 i/s - 7.89x (± 0.00) slower
1257
+ # Dry::Transaction: 4978.1 i/s - 20.96x (± 0.00) slower
1258
+ ```
1244
1259
  </details>
1245
1260
 
1246
1261
  https://github.com/serradura/u-case/blob/master/benchmarks/use_case/with_failure_result.rb
1247
1262
 
1248
1263
  ---
1249
1264
 
1250
- ### `Micro::Case::Flow`
1265
+ ### `Micro::Case::Flow` (v2.6.0)
1251
1266
 
1252
1267
  | Gems / Abstraction | [Success results](https://github.com/serradura/u-case/blob/master/benchmarks/flow/with_success_result.rb#L40) | [Failure results](https://github.com/serradura/u-case/blob/master/benchmarks/flow/with_failure_result.rb#L40) |
1253
1268
  | ------------------ | ----------------: | ----------------: |
1254
1269
  | Micro::Case::Flow | _**The Fastest**_ | _**The Fastest**_ |
1255
1270
  | Micro::Case::Safe::Flow | 0x slower | 0x slower |
1256
- | Interactor::Organizer | 1.47x slower | 5.51x slower |
1271
+ | Interactor::Organizer | 1.27x slower | 5.48x slower |
1257
1272
 
1258
1273
  \* The `Dry::Monads`, `Dry::Transaction`, `Trailblazer::Operation` are out of this analysis because all of them doesn't have this kind of feature.
1259
1274
 
1260
1275
  <details>
1261
1276
  <summary><strong>Success results</strong> - Show the full benchmark/ips results.</summary>
1262
1277
 
1263
- ```ruby
1264
- # Warming up --------------------------------------
1265
- # Interactor::Organizer 4.880k i/100ms
1266
- # Micro::Case::Flow 7.035k i/100ms
1267
- # Micro::Case::Safe::Flow 7.059k i/100ms
1268
-
1269
- # Calculating -------------------------------------
1270
- # Interactor::Organizer 50.208k1.3%) i/s - 253.760k in 5.055099s
1271
- # Micro::Case::Flow 73.791k0.9%) i/s - 372.855k in 5.053311s
1272
- # Micro::Case::Safe::Flow 73.314k (± 1.1%) i/s - 367.068k in 5.007473s
1273
-
1274
- # Comparison:
1275
- # Micro::Case::Flow: 73790.7 i/s
1276
- # Micro::Case::Safe::Flow: 73313.7 i/s - same-ish: difference falls within error
1277
- # Interactor::Organizer: 50207.7 i/s - 1.47x slower
1278
- ```
1278
+ ```ruby
1279
+ # Warming up --------------------------------------
1280
+ # Interactor::Organizer 4.765k i/100ms
1281
+ # Micro::Case::Flow 5.372k i/100ms
1282
+ # Micro::Case::Safe::Flow 5.855k i/100ms
1283
+ # Calculating -------------------------------------
1284
+ # Interactor::Organizer 48.598k (± 5.2%) i/s - 243.015k in 5.014307s
1285
+ # Micro::Case::Flow 61.606k4.4%) i/s - 311.576k in 5.068602s
1286
+ # Micro::Case::Safe::Flow 60.688k4.8%) i/s - 304.460k in 5.028877s
1287
+
1288
+ # Comparison:
1289
+ # Micro::Case::Flow: 61606.3 i/s
1290
+ # Micro::Case::Safe::Flow: 60688.3 i/s - same-ish: difference falls within error
1291
+ # Interactor::Organizer: 48598.2 i/s - 1.27x slower\
1292
+ ```
1279
1293
  </details>
1280
1294
 
1281
1295
  <details>
1282
1296
  <summary><strong>Failure results</strong> - Show the full benchmark/ips results.</summary>
1283
1297
 
1284
- ```ruby
1285
- # Warming up --------------------------------------
1286
- # Interactor::Organizer 2.372k i/100ms
1287
- # Micro::Case::Flow 12.802k i/100ms
1288
- # Micro::Case::Safe::Flow 12.673k i/100ms
1289
-
1290
- # Calculating -------------------------------------
1291
- # Interactor::Organizer 24.522k (± 2.0%) i/s - 123.344k in 5.032159s
1292
- # Micro::Case::Flow 135.122k1.7%) i/s - 678.506k in 5.022903s
1293
- # Micro::Case::Safe::Flow 133.980k1.4%) i/s - 671.669k in 5.014181s
1294
-
1295
- # Comparison:
1296
- # Micro::Case::Flow: 135122.0 i/s
1297
- # Micro::Case::Safe::Flow: 133979.8 i/s - same-ish: difference falls within error
1298
- # Interactor::Organizer: 24521.8 i/s - 5.51x slower
1299
- ```
1298
+ ```ruby
1299
+ # Warming up --------------------------------------
1300
+ # Interactor::Organizer 2.209k i/100ms
1301
+ # Micro::Case::Flow 11.508k i/100ms
1302
+ # Micro::Case::Safe::Flow 11.605k i/100ms
1303
+
1304
+ # Calculating -------------------------------------
1305
+ # Interactor::Organizer 22.592k (± 2.8%) i/s - 114.868k in 5.088685s
1306
+ # Micro::Case::Flow 123.629k2.9%) i/s - 621.432k in 5.030844s
1307
+ # Micro::Case::Safe::Flow 123.862k3.0%) i/s - 626.670k in 5.064097s
1308
+
1309
+ # Comparison:
1310
+ # Micro::Case::Safe::Flow: 123862.4 i/s
1311
+ # Micro::Case::Flow: 123629.3 i/s - same-ish: difference falls within error
1312
+ # Interactor::Organizer: 22592.2 i/s - 5.48x slower
1313
+ ```
1300
1314
  </details>
1301
1315
 
1302
1316
  https://github.com/serradura/u-case/tree/master/benchmarks/flow