u-case 3.1.0 → 4.2.1
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 +4 -4
- data/.travis.sh +30 -10
- data/Gemfile +20 -9
- data/README.md +160 -134
- data/README.pt-BR.md +161 -136
- data/lib/micro/case.rb +68 -15
- data/lib/micro/case/error.rb +4 -1
- data/lib/micro/case/result.rb +42 -8
- data/lib/micro/case/result/transitions.rb +1 -4
- data/lib/micro/case/result/wrapper.rb +45 -0
- data/lib/micro/case/safe.rb +1 -1
- data/lib/micro/case/strict.rb +2 -2
- data/lib/micro/case/utils.rb +19 -10
- data/lib/micro/case/version.rb +1 -1
- data/lib/micro/cases.rb +7 -0
- data/lib/micro/cases/error.rb +13 -0
- data/lib/micro/cases/flow.rb +23 -14
- data/lib/micro/cases/map.rb +39 -0
- data/lib/micro/cases/safe/flow.rb +2 -2
- data/lib/micro/cases/utils.rb +21 -0
- data/u-case.gemspec +3 -3
- metadata +12 -6
data/lib/micro/case/error.rb
CHANGED
@@ -52,7 +52,10 @@ module Micro
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def self.by_wrong_usage?(exception)
|
55
|
-
|
55
|
+
case exception
|
56
|
+
when Kind::Error, ArgumentError, InvalidResult, UnexpectedResult then true
|
57
|
+
else false
|
58
|
+
end
|
56
59
|
end
|
57
60
|
end
|
58
61
|
end
|
data/lib/micro/case/result.rb
CHANGED
@@ -5,6 +5,7 @@ require 'set'
|
|
5
5
|
module Micro
|
6
6
|
class Case
|
7
7
|
class Result
|
8
|
+
require 'micro/case/result/wrapper'
|
8
9
|
require 'micro/case/result/transitions'
|
9
10
|
|
10
11
|
Kind::Types.add(self)
|
@@ -22,20 +23,35 @@ module Micro
|
|
22
23
|
|
23
24
|
alias value data
|
24
25
|
|
25
|
-
def initialize(transitions_mapper =
|
26
|
+
def initialize(transitions_mapper = Transitions::MapEverything)
|
27
|
+
enable_transitions = @@transitions_enabled
|
28
|
+
|
29
|
+
@__is_unknown = true
|
26
30
|
@__accumulated_data = {}
|
31
|
+
@__tracked_use_cases = Set.new
|
27
32
|
@__accessible_attributes = {}
|
28
33
|
|
29
|
-
enable_transitions = @@transitions_enabled
|
30
|
-
|
31
34
|
@__transitions = enable_transitions ? [] : Kind::Empty::ARRAY
|
32
|
-
@__transitions_mapper = transitions_mapper
|
35
|
+
@__transitions_mapper = transitions_mapper if enable_transitions
|
36
|
+
end
|
37
|
+
|
38
|
+
def inspect
|
39
|
+
pretty_type = @__success ? 'Success' : 'Failure'
|
40
|
+
|
41
|
+
instance_info = '%s (%s) type=:%s data=%s' % [pretty_type, self.class, @type, data]
|
42
|
+
transitions_info = ' transitions=%d' % [@__transitions.size] if Micro::Case::Result.transitions_enabled?
|
43
|
+
|
44
|
+
"#<#{instance_info}#{transitions_info}>"
|
33
45
|
end
|
34
46
|
|
35
47
|
def to_ary
|
36
48
|
[data, type]
|
37
49
|
end
|
38
50
|
|
51
|
+
def to_sym
|
52
|
+
@__success ? :success : :failure
|
53
|
+
end
|
54
|
+
|
39
55
|
def [](key)
|
40
56
|
data[key]
|
41
57
|
end
|
@@ -53,7 +69,7 @@ module Micro
|
|
53
69
|
end
|
54
70
|
|
55
71
|
def slice(*keys)
|
56
|
-
Utils.
|
72
|
+
Utils::Hashes.slice(data, keys)
|
57
73
|
end
|
58
74
|
|
59
75
|
def success?
|
@@ -64,6 +80,10 @@ module Micro
|
|
64
80
|
!success?
|
65
81
|
end
|
66
82
|
|
83
|
+
def unknown?
|
84
|
+
@__is_unknown
|
85
|
+
end
|
86
|
+
|
67
87
|
def accessible_attributes
|
68
88
|
@__accessible_attributes.keys
|
69
89
|
end
|
@@ -71,6 +91,7 @@ module Micro
|
|
71
91
|
def on_success(expected_type = nil)
|
72
92
|
return self unless __success_type?(expected_type)
|
73
93
|
|
94
|
+
@__is_unknown = false
|
74
95
|
hook_data = expected_type.nil? ? self : data
|
75
96
|
|
76
97
|
yield(hook_data, @use_case)
|
@@ -81,6 +102,7 @@ module Micro
|
|
81
102
|
def on_failure(expected_type = nil)
|
82
103
|
return self unless __failure_type?(expected_type)
|
83
104
|
|
105
|
+
@__is_unknown = false
|
84
106
|
hook_data = expected_type.nil? ? self : data
|
85
107
|
|
86
108
|
yield(hook_data, @use_case)
|
@@ -98,6 +120,14 @@ module Micro
|
|
98
120
|
self
|
99
121
|
end
|
100
122
|
|
123
|
+
def on_unknown
|
124
|
+
return self unless unknown?
|
125
|
+
|
126
|
+
yield(self, @use_case)
|
127
|
+
|
128
|
+
self
|
129
|
+
end
|
130
|
+
|
101
131
|
def then(use_case = nil, attributes = nil, &block)
|
102
132
|
can_yield_self = respond_to?(:yield_self)
|
103
133
|
|
@@ -159,9 +189,13 @@ module Micro
|
|
159
189
|
|
160
190
|
@__accumulated_data.merge!(@data)
|
161
191
|
|
162
|
-
use_case_attributes = Utils.
|
192
|
+
use_case_attributes = Utils::Hashes.symbolize_keys(@use_case.attributes)
|
163
193
|
|
164
|
-
|
194
|
+
unless @__tracked_use_cases.member?(use_case_class = @use_case.class)
|
195
|
+
@__tracked_use_cases.add(use_case_class)
|
196
|
+
|
197
|
+
__update_accessible_attributes(use_case_attributes)
|
198
|
+
end
|
165
199
|
|
166
200
|
__set_transition(use_case_attributes) unless @__transitions.frozen?
|
167
201
|
|
@@ -171,7 +205,7 @@ module Micro
|
|
171
205
|
def __set_accessible_attributes__(arg)
|
172
206
|
return arg unless arg.is_a?(Hash)
|
173
207
|
|
174
|
-
attributes = Utils.
|
208
|
+
attributes = Utils::Hashes.symbolize_keys(arg)
|
175
209
|
|
176
210
|
__update_accessible_attributes(attributes)
|
177
211
|
__fetch_accessible_attributes
|
@@ -5,11 +5,9 @@ module Micro
|
|
5
5
|
class Result
|
6
6
|
class Transitions
|
7
7
|
MapEverything = -> (result, use_case_attributes) do
|
8
|
-
result_track = result.success? ? :success : :failure
|
9
|
-
|
10
8
|
{
|
11
9
|
use_case: { class: result.use_case.class, attributes: use_case_attributes },
|
12
|
-
|
10
|
+
result.to_sym => { type: result.type, result: result.data },
|
13
11
|
accessible_attributes: result.accessible_attributes
|
14
12
|
}
|
15
13
|
end
|
@@ -17,4 +15,3 @@ module Micro
|
|
17
15
|
end
|
18
16
|
end
|
19
17
|
end
|
20
|
-
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Micro
|
4
|
+
class Case
|
5
|
+
class Result
|
6
|
+
class Wrapper
|
7
|
+
def initialize(result)
|
8
|
+
@__is_unknown = true
|
9
|
+
|
10
|
+
@result = result
|
11
|
+
end
|
12
|
+
|
13
|
+
def failure(type = nil)
|
14
|
+
return if @result.success?
|
15
|
+
|
16
|
+
if result_type?(type)
|
17
|
+
@__is_unknown = false
|
18
|
+
|
19
|
+
yield(@result)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def success(type = nil)
|
24
|
+
return if @result.failure?
|
25
|
+
|
26
|
+
if result_type?(type)
|
27
|
+
@__is_unknown = false
|
28
|
+
|
29
|
+
yield(@result)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def unknown
|
34
|
+
return yield(@result) if @__is_unknown
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def result_type?(type)
|
40
|
+
type.nil? || @result.type == type
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/micro/case/safe.rb
CHANGED
data/lib/micro/case/strict.rb
CHANGED
@@ -3,10 +3,10 @@
|
|
3
3
|
module Micro
|
4
4
|
class Case
|
5
5
|
class Strict < ::Micro::Case
|
6
|
-
include Micro::Attributes::Features::
|
6
|
+
include Micro::Attributes::Features::Initialize::Strict
|
7
7
|
|
8
8
|
class Safe < ::Micro::Case::Safe
|
9
|
-
include Micro::Attributes::Features::
|
9
|
+
include Micro::Attributes::Features::Initialize::Strict
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
data/lib/micro/case/utils.rb
CHANGED
@@ -3,25 +3,34 @@
|
|
3
3
|
module Micro
|
4
4
|
class Case
|
5
5
|
module Utils
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
|
7
|
+
module Hashes
|
8
|
+
def self.respond_to?(hash, method)
|
9
|
+
Kind.of(Hash, hash).respond_to?(method)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.symbolize_keys(hash)
|
13
|
+
return hash.transform_keys { |key| key.to_sym rescue key } if respond_to?(hash, :transform_keys)
|
14
|
+
|
10
15
|
hash.each_with_object({}) do |(k, v), memo|
|
11
16
|
key = k.to_sym rescue k
|
12
|
-
|
13
17
|
memo[key] = v
|
14
18
|
end
|
15
19
|
end
|
16
|
-
end
|
17
20
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
21
|
+
def self.stringify_keys(hash)
|
22
|
+
return hash.transform_keys(&:to_s) if respond_to?(hash, :transform_keys)
|
23
|
+
|
24
|
+
hash.each_with_object({}) { |(k, v), memo| memo[k.to_s] = v }
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.slice(hash, keys)
|
28
|
+
return hash.slice(*keys) if respond_to?(hash, :slice)
|
29
|
+
|
22
30
|
hash.select { |key, _value| keys.include?(key) }
|
23
31
|
end
|
24
32
|
end
|
33
|
+
|
25
34
|
end
|
26
35
|
end
|
27
36
|
end
|
data/lib/micro/case/version.rb
CHANGED
data/lib/micro/cases.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'micro/cases/utils'
|
4
|
+
require 'micro/cases/error'
|
3
5
|
require 'micro/cases/flow'
|
4
6
|
require 'micro/cases/safe/flow'
|
7
|
+
require 'micro/cases/map'
|
5
8
|
|
6
9
|
module Micro
|
7
10
|
module Cases
|
@@ -12,5 +15,9 @@ module Micro
|
|
12
15
|
def self.safe_flow(args)
|
13
16
|
Safe::Flow.build(args)
|
14
17
|
end
|
18
|
+
|
19
|
+
def self.map(args)
|
20
|
+
Map.build(args)
|
21
|
+
end
|
15
22
|
end
|
16
23
|
end
|
data/lib/micro/cases/flow.rb
CHANGED
@@ -3,20 +3,15 @@
|
|
3
3
|
module Micro
|
4
4
|
module Cases
|
5
5
|
class Flow
|
6
|
-
|
7
|
-
|
8
|
-
end
|
6
|
+
IsAUseCaseWithDefaults = -> arg { arg.is_a?(Array) && Micro.case?(arg[0]) && arg[1].is_a?(Hash) }
|
7
|
+
IsAValidUseCase = -> use_case { Micro.case?(use_case) || IsAUseCaseWithDefaults[use_case] }
|
9
8
|
|
10
9
|
attr_reader :use_cases
|
11
10
|
|
12
|
-
def self.map_use_cases(arg)
|
13
|
-
arg.is_a?(Flow) ? arg.use_cases : Array(arg)
|
14
|
-
end
|
15
|
-
|
16
11
|
def self.build(args)
|
17
|
-
use_cases =
|
12
|
+
use_cases = Utils.map_use_cases(args)
|
18
13
|
|
19
|
-
raise InvalidUseCases if use_cases.
|
14
|
+
raise Error::InvalidUseCases if use_cases.none?(&IsAValidUseCase)
|
20
15
|
|
21
16
|
new(use_cases)
|
22
17
|
end
|
@@ -27,8 +22,12 @@ module Micro
|
|
27
22
|
@first = @next_ones.shift
|
28
23
|
end
|
29
24
|
|
25
|
+
def inspect
|
26
|
+
'#<(%s) use_cases=%s>' % [self.class, @use_cases]
|
27
|
+
end
|
28
|
+
|
30
29
|
def call!(input:, result:)
|
31
|
-
first_result =
|
30
|
+
first_result = __call_use_case(@first, result, input)
|
32
31
|
|
33
32
|
return first_result if @next_ones.empty?
|
34
33
|
|
@@ -36,7 +35,11 @@ module Micro
|
|
36
35
|
end
|
37
36
|
|
38
37
|
def call(input = Kind::Empty::HASH)
|
39
|
-
call!(input: input, result: Case::Result.new)
|
38
|
+
result = call!(input: input, result: Case::Result.new)
|
39
|
+
|
40
|
+
return result unless block_given?
|
41
|
+
|
42
|
+
yield ::Micro::Case::Result::Wrapper.new(result)
|
40
43
|
end
|
41
44
|
|
42
45
|
alias __call__ call
|
@@ -68,17 +71,23 @@ module Micro
|
|
68
71
|
raise Case::Error::InvalidInvocationOfTheThenMethod.new("#{self.class.name}#")
|
69
72
|
end
|
70
73
|
|
71
|
-
def
|
72
|
-
use_case
|
74
|
+
def __call_use_case(use_case, result, input)
|
75
|
+
__build_use_case(use_case, result, input).__call__
|
73
76
|
end
|
74
77
|
|
75
78
|
def __call_next_use_cases(first_result)
|
76
79
|
@next_ones.reduce(first_result) do |result, use_case|
|
77
80
|
break result if result.failure?
|
78
81
|
|
79
|
-
|
82
|
+
__call_use_case(use_case, result, result.data)
|
80
83
|
end
|
81
84
|
end
|
85
|
+
|
86
|
+
def __build_use_case(use_case, result, input)
|
87
|
+
return use_case.__new__(result, input) unless use_case.is_a?(Array)
|
88
|
+
|
89
|
+
use_case[0].__new__(result, input.merge(use_case[1]))
|
90
|
+
end
|
82
91
|
end
|
83
92
|
end
|
84
93
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Micro
|
4
|
+
module Cases
|
5
|
+
class Map
|
6
|
+
IsAUseCaseOrFlowWithDefaults = -> arg { arg.is_a?(Array) && Micro.case_or_flow?(arg[0]) && arg[1].is_a?(Hash) }
|
7
|
+
IsAUseCaseOrFlow = -> arg { Micro.case_or_flow?(arg) || IsAUseCaseOrFlowWithDefaults[arg] }
|
8
|
+
HasValidArgs = -> (args) { Kind.of(Array, args).all?(&IsAUseCaseOrFlow) }
|
9
|
+
|
10
|
+
attr_reader :use_cases
|
11
|
+
|
12
|
+
def self.build(args)
|
13
|
+
raise Error::InvalidUseCases unless HasValidArgs[args]
|
14
|
+
|
15
|
+
new(args)
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(use_cases)
|
19
|
+
@use_cases = use_cases
|
20
|
+
end
|
21
|
+
|
22
|
+
GetUseCaseResult = -> (hash) do
|
23
|
+
-> (use_case) do
|
24
|
+
return use_case.call(hash) unless use_case.is_a?(Array)
|
25
|
+
|
26
|
+
use_case[0].call(hash.merge(use_case[1]))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def call(arg = {})
|
31
|
+
hash = Kind.of(Hash, arg)
|
32
|
+
|
33
|
+
use_cases.map(&GetUseCaseResult[hash])
|
34
|
+
end
|
35
|
+
|
36
|
+
private_constant :HasValidArgs, :IsAUseCaseOrFlow, :IsAUseCaseOrFlowWithDefaults, :GetUseCaseResult
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -4,8 +4,8 @@ module Micro
|
|
4
4
|
module Cases
|
5
5
|
module Safe
|
6
6
|
class Flow < Cases::Flow
|
7
|
-
private def
|
8
|
-
instance = use_case
|
7
|
+
private def __call_use_case(use_case, result, input)
|
8
|
+
instance = __build_use_case(use_case, result, input)
|
9
9
|
instance.__call__
|
10
10
|
rescue => exception
|
11
11
|
raise exception if Case::Error.by_wrong_usage?(exception)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Micro
|
4
|
+
module Cases
|
5
|
+
|
6
|
+
module Utils
|
7
|
+
def self.map_use_cases(args)
|
8
|
+
collection = args.is_a?(Array) && args.size == 1 ? args[0] : args
|
9
|
+
|
10
|
+
Array(collection).each_with_object([]) do |arg, memo|
|
11
|
+
if arg.is_a?(Flow)
|
12
|
+
arg.use_cases.each { |use_case| memo << use_case }
|
13
|
+
else
|
14
|
+
memo << arg
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|