u-case 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3ba53faeaf465b491f94a686da7fc2537e9c50108b18162d11c473246e6a531e
4
- data.tar.gz: 6b91c842ad57b917678649f4003f34ade8459a70c56938d2e226a4d8322e855d
3
+ metadata.gz: e4b75e85c821351da3ee8298a9c9d97980be292488746a25a48510d6ad43b1d5
4
+ data.tar.gz: e8bd964807111d6895f113e0951d0d2c643664110646f433edb35883e0d585a9
5
5
  SHA512:
6
- metadata.gz: 8d4790abfb49211a69d9874900e83a0237d5fe0f0b288102e9bcff33fd932db4192e66ea2e5814990da2d5e92b5499dd93173257433639e2248463f2b3c991e8
7
- data.tar.gz: e2bd4e73018961d931a76298dacf8000836d26f2331f975b777bc0371dcfe84d2064a51ef12636f31eaf22986a76b97f99e7cbe16b653a1bd1923ae5f8f4f125
6
+ metadata.gz: 7395bdc572be3cce61d7358333e2bade896e9c240012c443e6015f02bae8022cad7d90323866b0229341729375ff63d381860418fcd2cac3a0f6608669fe59c5
7
+ data.tar.gz: 448b78286a29b60ae3bf79f7786011572bbb39cd5f9cf2091f32be7b8d1017b7e8973c2bea1e0a1d1f9c65c5e96c764261d1a3b9d7584b765ea937aca998291b
data/.tool-versions CHANGED
@@ -1 +1 @@
1
- ruby 2.6.3
1
+ ruby 2.6.5
data/README.md CHANGED
@@ -18,7 +18,7 @@ The main project goals are:
18
18
  > 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.
19
19
 
20
20
  ## Table of Contents <!-- omit in toc -->
21
- - [μ-case (Micro::Case)](#%ce%bc-case-microcase)
21
+ - [μ-case (Micro::Case)](#μ-case-microcase)
22
22
  - [Required Ruby version](#required-ruby-version)
23
23
  - [Dependencies](#dependencies)
24
24
  - [Installation](#installation)
@@ -31,13 +31,14 @@ The main project goals are:
31
31
  - [How to use the result hooks?](#how-to-use-the-result-hooks)
32
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)
33
33
  - [What happens if a result hook was declared multiple times?](#what-happens-if-a-result-hook-was-declared-multiple-times)
34
+ - [How to use the Micro::Case::Result#then method?](#how-to-use-the-microcaseresultthen-method)
34
35
  - [Micro::Case::Flow - How to compose use cases?](#microcaseflow---how-to-compose-use-cases)
35
36
  - [Is it possible to compose a use case flow with other ones?](#is-it-possible-to-compose-a-use-case-flow-with-other-ones)
36
37
  - [Is it possible a flow accumulates its input and merges each success result to use as the argument of their use cases?](#is-it-possible-a-flow-accumulates-its-input-and-merges-each-success-result-to-use-as-the-argument-of-their-use-cases)
37
38
  - [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)
38
39
  - [Micro::Case::Strict - What is a strict use case?](#microcasestrict---what-is-a-strict-use-case)
39
40
  - [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)
40
- - [u-case/with_validation - How to validate use case attributes?](#u-casewithvalidation---how-to-validate-use-case-attributes)
41
+ - [u-case/with_validation - How to validate use case attributes?](#u-casewith_validation---how-to-validate-use-case-attributes)
41
42
  - [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)
42
43
  - [Benchmarks](#benchmarks)
43
44
  - [Micro::Case](#microcase)
@@ -47,10 +48,10 @@ The main project goals are:
47
48
  - [Micro::Case::Flow](#microcaseflow)
48
49
  - [Comparisons](#comparisons)
49
50
  - [Examples](#examples)
50
- - [1️⃣ Rails App (API)](#1%ef%b8%8f%e2%83%a3-rails-app-api)
51
- - [2️⃣ CLI calculator](#2%ef%b8%8f%e2%83%a3-cli-calculator)
52
- - [3️⃣ Users creation](#3%ef%b8%8f%e2%83%a3-users-creation)
53
- - [4️⃣ Rescuing exception inside of the use cases](#4%ef%b8%8f%e2%83%a3-rescuing-exception-inside-of-the-use-cases)
51
+ - [1️⃣ Rails App (API)](#1️⃣-rails-app-api)
52
+ - [2️⃣ CLI calculator](#2️⃣-cli-calculator)
53
+ - [3️⃣ Users creation](#3️⃣-users-creation)
54
+ - [4️⃣ Rescuing exception inside of the use cases](#4️⃣-rescuing-exception-inside-of-the-use-cases)
54
55
  - [Development](#development)
55
56
  - [Contributing](#contributing)
56
57
  - [License](#license)
@@ -145,6 +146,7 @@ A `Micro::Case::Result` stores the use cases output data. These are their main m
145
146
  - `#type` a Symbol which gives meaning for the result, this is useful to declare different types of failures or success.
146
147
  - `#on_success` or `#on_failure` are hook methods that help you define the application flow.
147
148
  - `#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).
149
+ - `#then` allows if the current result is a success, the `then` method will allow to applying a new use case for its value.
148
150
 
149
151
  [⬆️ Back to Top](#table-of-contents-)
150
152
 
@@ -415,6 +417,48 @@ accum # 24
415
417
  result.value * 4 == accum # true
416
418
  ```
417
419
 
420
+ #### How to use the `Micro::Case::Result#then` method?
421
+
422
+ ```ruby
423
+ class ForbidNegativeNumber < Micro::Case
424
+ attribute :number
425
+
426
+ def call!
427
+ return Success { attributes } if number >= 0
428
+
429
+ Failure { attributes }
430
+ end
431
+ end
432
+
433
+ class Add3 < Micro::Case
434
+ attribute :number
435
+
436
+ def call!
437
+ Success { { number: number + 3 } }
438
+ end
439
+ end
440
+
441
+ result1 =
442
+ ForbidNegativeNumber
443
+ .call(number: -1)
444
+ .then(Add3)
445
+
446
+ result1.type # :error
447
+ result1.value # {'number' => -1}
448
+ result1.failure? # true
449
+
450
+ # ---
451
+
452
+ result2 =
453
+ ForbidNegativeNumber
454
+ .call(number: 1)
455
+ .then(Add3)
456
+
457
+ result2.type # :ok
458
+ result2.value # {'number' => 4}
459
+ result2.success? # true
460
+ ```
461
+
418
462
  [⬆️ Back to Top](#table-of-contents-)
419
463
 
420
464
  ### `Micro::Case::Flow` - How to compose use cases?
@@ -9,20 +9,36 @@ module Micro
9
9
  def initialize(klass); super(klass.name + MESSAGE); end
10
10
  end
11
11
 
12
- ResultIsAlreadyDefined = ArgumentError.new('result is already defined'.freeze)
12
+ class ResultIsAlreadyDefined < ArgumentError
13
+ def initialize; super('result is already defined'.freeze); end
14
+ end
13
15
 
14
- InvalidResultType = TypeError.new('type must be a Symbol'.freeze)
15
- InvalidResultInstance = ArgumentError.new('argument must be an instance of Micro::Case::Result'.freeze)
16
+ class InvalidResultType < TypeError
17
+ def initialize; super('type must be a Symbol'.freeze); end
18
+ end
16
19
 
17
- InvalidUseCase = TypeError.new('use case must be a kind or an instance of Micro::Case'.freeze)
18
- InvalidUseCases = ArgumentError.new('argument must be a collection of `Micro::Case` classes'.freeze)
20
+ class InvalidResultInstance < ArgumentError
21
+ def initialize; super('argument must be an instance of Micro::Case::Result'.freeze); end
22
+ end
19
23
 
20
- UndefinedFlow = ArgumentError.new("This class hasn't declared its flow. Please, use the `flow()` macro to define one.".freeze)
24
+ class InvalidUseCase < TypeError
25
+ def initialize; super('use case must be a kind or an instance of Micro::Case'.freeze); end
26
+ end
21
27
 
22
- class InvalidAccessToTheUseCaseObject < StandardError
23
- MSG = 'only a failure result can access its use case object'.freeze
28
+ class InvalidUseCases < ArgumentError
29
+ def initialize; super('argument must be a collection of `Micro::Case` classes'.freeze); end
30
+ end
24
31
 
25
- def initialize(message = MSG); super; end
32
+ class InvalidInvocationOfTheThenMethod < StandardError
33
+ def initialize; super('Invalid invocation of the Micro::Case::Result#then method'); end
34
+ end
35
+
36
+ class UndefinedFlow < ArgumentError
37
+ def initialize; super("This class hasn't declared its flow. Please, use the `flow()` macro to define one.".freeze); end
38
+ end
39
+
40
+ class InvalidAccessToTheUseCaseObject < StandardError
41
+ def initialize; super('only a failure result can access its use case object'.freeze); end
26
42
  end
27
43
 
28
44
  module ByWrongUsage
@@ -52,6 +52,25 @@ module Micro
52
52
  self.tap { yield(data, @use_case) }
53
53
  end
54
54
 
55
+ def then(arg = nil, &block)
56
+ can_yield_self = respond_to?(:yield_self)
57
+
58
+ if block
59
+ raise Error::InvalidInvocationOfTheThenMethod if arg
60
+ raise NotImplementedError if !can_yield_self
61
+
62
+ yield_self(&block)
63
+ else
64
+ return yield_self if !arg && can_yield_self
65
+
66
+ raise Error::InvalidInvocationOfTheThenMethod if !is_a_use_case?(arg)
67
+
68
+ return self if failure?
69
+
70
+ arg.call(self.value)
71
+ end
72
+ end
73
+
55
74
  private
56
75
 
57
76
  def success_type?(expected_type)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Micro
4
4
  class Case
5
- VERSION = '2.2.0'.freeze
5
+ VERSION = '2.3.0'.freeze
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: u-case
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rodrigo Serradura
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-12-12 00:00:00.000000000 Z
11
+ date: 2019-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: u-attributes
@@ -103,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
103
  - !ruby/object:Gem::Version
104
104
  version: '0'
105
105
  requirements: []
106
- rubygems_version: 3.0.3
106
+ rubygems_version: 3.0.6
107
107
  signing_key:
108
108
  specification_version: 4
109
109
  summary: Create simple and powerful use cases as objects.