u-case 2.6.0 → 3.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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