u-case 4.0.0 → 4.2.2
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 +32 -10
- data/Gemfile +20 -9
- data/README.md +103 -99
- data/README.pt-BR.md +106 -105
- data/lib/micro/case.rb +70 -14
- data/lib/micro/case/result.rb +36 -6
- data/lib/micro/case/result/transitions.rb +0 -1
- data/lib/micro/case/result/wrapper.rb +50 -0
- data/lib/micro/case/safe.rb +1 -1
- 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 +27 -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
- metadata +6 -2
data/lib/micro/case.rb
CHANGED
@@ -7,6 +7,7 @@ require 'micro/case/version'
|
|
7
7
|
|
8
8
|
module Micro
|
9
9
|
class Case
|
10
|
+
require 'micro/cases/utils'
|
10
11
|
require 'micro/case/utils'
|
11
12
|
require 'micro/case/error'
|
12
13
|
require 'micro/case/result'
|
@@ -16,10 +17,18 @@ module Micro
|
|
16
17
|
|
17
18
|
require 'micro/cases'
|
18
19
|
|
19
|
-
include Micro::Attributes
|
20
|
+
include Micro::Attributes
|
20
21
|
|
21
|
-
def self.call(
|
22
|
-
new
|
22
|
+
def self.call(input = Kind::Empty::HASH)
|
23
|
+
result = __new__(Result.new, input).__call__
|
24
|
+
|
25
|
+
return result unless block_given?
|
26
|
+
|
27
|
+
result_wrapper = Result::Wrapper.new(result)
|
28
|
+
|
29
|
+
yield(result_wrapper)
|
30
|
+
|
31
|
+
result_wrapper.output
|
23
32
|
end
|
24
33
|
|
25
34
|
INVALID_INVOCATION_OF_THE_THEN_METHOD =
|
@@ -47,7 +56,7 @@ module Micro
|
|
47
56
|
end
|
48
57
|
|
49
58
|
def self.flow(*args)
|
50
|
-
@__flow_use_cases = args
|
59
|
+
@__flow_use_cases = Cases::Utils.map_use_cases(args)
|
51
60
|
end
|
52
61
|
|
53
62
|
class << self
|
@@ -81,6 +90,8 @@ module Micro
|
|
81
90
|
new(input).__set_result__(result)
|
82
91
|
end
|
83
92
|
|
93
|
+
private_class_method :new
|
94
|
+
|
84
95
|
def self.__flow_builder__
|
85
96
|
Cases::Flow
|
86
97
|
end
|
@@ -122,6 +133,28 @@ module Micro
|
|
122
133
|
__flow_set(__flow_use_cases_get) if !__flow_get__ && __flow_use_cases
|
123
134
|
end
|
124
135
|
|
136
|
+
InspectKey = :__inspect_key__ # :nodoc:
|
137
|
+
|
138
|
+
def self.inspect
|
139
|
+
ids = (Thread.current[InspectKey] ||= [])
|
140
|
+
|
141
|
+
if ids.include?(object_id)
|
142
|
+
return sprintf('#<%s: ...>', self)
|
143
|
+
end
|
144
|
+
|
145
|
+
begin
|
146
|
+
ids << object_id
|
147
|
+
|
148
|
+
if __flow_use_cases
|
149
|
+
return '<%s (%s) use_cases=%s>' % [self, __flow_builder__, @__flow_use_cases]
|
150
|
+
else
|
151
|
+
return '<%s (%s) attributes=%s>' % [self, self.superclass, attributes]
|
152
|
+
end
|
153
|
+
ensure
|
154
|
+
ids.pop
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
125
158
|
def initialize(input)
|
126
159
|
__setup_use_case(input)
|
127
160
|
end
|
@@ -131,7 +164,7 @@ module Micro
|
|
131
164
|
end
|
132
165
|
|
133
166
|
def __call__
|
134
|
-
|
167
|
+
__call_the_use_case_or_its_flow
|
135
168
|
end
|
136
169
|
|
137
170
|
def __set_result__(result)
|
@@ -145,12 +178,21 @@ module Micro
|
|
145
178
|
|
146
179
|
private
|
147
180
|
|
181
|
+
def call(use_case, defaults = Kind::Empty::HASH)
|
182
|
+
raise Error::InvalidUseCase unless ::Micro.case_or_flow?(use_case)
|
183
|
+
|
184
|
+
input =
|
185
|
+
defaults.empty? ? attributes : attributes.merge(Utils::Hashes.stringify_keys(defaults))
|
186
|
+
|
187
|
+
use_case.__new__(@__result, input).__call__
|
188
|
+
end
|
189
|
+
|
148
190
|
def apply(name)
|
149
191
|
method(name)
|
150
192
|
end
|
151
193
|
|
152
|
-
def
|
153
|
-
return
|
194
|
+
def __call_the_use_case_or_its_flow
|
195
|
+
return __call_the_use_case_flow if __call_the_use_case_flow?
|
154
196
|
|
155
197
|
__call_use_case
|
156
198
|
end
|
@@ -171,11 +213,11 @@ module Micro
|
|
171
213
|
raise Error::UnexpectedResult.new("#{self.class.name}#call!")
|
172
214
|
end
|
173
215
|
|
174
|
-
def
|
216
|
+
def __call_the_use_case_flow?
|
175
217
|
self.class.__flow_get__
|
176
218
|
end
|
177
219
|
|
178
|
-
def
|
220
|
+
def __call_the_use_case_flow
|
179
221
|
self.class.__flow_get__.call(@__input)
|
180
222
|
end
|
181
223
|
|
@@ -201,18 +243,32 @@ module Micro
|
|
201
243
|
__get_result(false, value, type)
|
202
244
|
end
|
203
245
|
|
204
|
-
def
|
205
|
-
@__result
|
246
|
+
def __get_result(is_success, value, type)
|
247
|
+
@__result.__set__(is_success, value, type, self)
|
206
248
|
end
|
207
249
|
|
208
|
-
def
|
209
|
-
|
250
|
+
def transaction(adapter = :activerecord)
|
251
|
+
raise NotImplementedError unless adapter == :activerecord
|
252
|
+
|
253
|
+
result = nil
|
254
|
+
|
255
|
+
ActiveRecord::Base.transaction do
|
256
|
+
result = yield
|
257
|
+
|
258
|
+
raise ActiveRecord::Rollback if result.failure?
|
259
|
+
end
|
260
|
+
|
261
|
+
result
|
210
262
|
end
|
211
263
|
|
212
264
|
private_constant :MapFailureType, :INVALID_INVOCATION_OF_THE_THEN_METHOD
|
213
265
|
end
|
214
266
|
|
267
|
+
def self.case?(arg)
|
268
|
+
arg.is_a?(Class) && arg < Case
|
269
|
+
end
|
270
|
+
|
215
271
|
def self.case_or_flow?(arg)
|
216
|
-
|
272
|
+
case?(arg) || arg.is_a?(Cases::Flow)
|
217
273
|
end
|
218
274
|
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)
|
@@ -23,15 +24,26 @@ module Micro
|
|
23
24
|
alias value data
|
24
25
|
|
25
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
35
|
@__transitions_mapper = transitions_mapper if enable_transitions
|
33
36
|
end
|
34
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}>"
|
45
|
+
end
|
46
|
+
|
35
47
|
def to_ary
|
36
48
|
[data, type]
|
37
49
|
end
|
@@ -57,7 +69,7 @@ module Micro
|
|
57
69
|
end
|
58
70
|
|
59
71
|
def slice(*keys)
|
60
|
-
Utils.
|
72
|
+
Utils::Hashes.slice(data, keys)
|
61
73
|
end
|
62
74
|
|
63
75
|
def success?
|
@@ -68,6 +80,10 @@ module Micro
|
|
68
80
|
!success?
|
69
81
|
end
|
70
82
|
|
83
|
+
def unknown?
|
84
|
+
@__is_unknown
|
85
|
+
end
|
86
|
+
|
71
87
|
def accessible_attributes
|
72
88
|
@__accessible_attributes.keys
|
73
89
|
end
|
@@ -75,6 +91,7 @@ module Micro
|
|
75
91
|
def on_success(expected_type = nil)
|
76
92
|
return self unless __success_type?(expected_type)
|
77
93
|
|
94
|
+
@__is_unknown = false
|
78
95
|
hook_data = expected_type.nil? ? self : data
|
79
96
|
|
80
97
|
yield(hook_data, @use_case)
|
@@ -85,6 +102,7 @@ module Micro
|
|
85
102
|
def on_failure(expected_type = nil)
|
86
103
|
return self unless __failure_type?(expected_type)
|
87
104
|
|
105
|
+
@__is_unknown = false
|
88
106
|
hook_data = expected_type.nil? ? self : data
|
89
107
|
|
90
108
|
yield(hook_data, @use_case)
|
@@ -102,6 +120,14 @@ module Micro
|
|
102
120
|
self
|
103
121
|
end
|
104
122
|
|
123
|
+
def on_unknown
|
124
|
+
return self unless unknown?
|
125
|
+
|
126
|
+
yield(self, @use_case)
|
127
|
+
|
128
|
+
self
|
129
|
+
end
|
130
|
+
|
105
131
|
def then(use_case = nil, attributes = nil, &block)
|
106
132
|
can_yield_self = respond_to?(:yield_self)
|
107
133
|
|
@@ -163,9 +189,13 @@ module Micro
|
|
163
189
|
|
164
190
|
@__accumulated_data.merge!(@data)
|
165
191
|
|
166
|
-
use_case_attributes = Utils.
|
192
|
+
use_case_attributes = Utils::Hashes.symbolize_keys(@use_case.attributes)
|
167
193
|
|
168
|
-
|
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
|
169
199
|
|
170
200
|
__set_transition(use_case_attributes) unless @__transitions.frozen?
|
171
201
|
|
@@ -175,7 +205,7 @@ module Micro
|
|
175
205
|
def __set_accessible_attributes__(arg)
|
176
206
|
return arg unless arg.is_a?(Hash)
|
177
207
|
|
178
|
-
attributes = Utils.
|
208
|
+
attributes = Utils::Hashes.symbolize_keys(arg)
|
179
209
|
|
180
210
|
__update_accessible_attributes(attributes)
|
181
211
|
__fetch_accessible_attributes
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Micro
|
4
|
+
class Case
|
5
|
+
class Result
|
6
|
+
class Wrapper
|
7
|
+
attr_reader :output
|
8
|
+
|
9
|
+
def initialize(result)
|
10
|
+
@result = result
|
11
|
+
@output = ::Kind::Undefined
|
12
|
+
|
13
|
+
@__is_unknown = true
|
14
|
+
end
|
15
|
+
|
16
|
+
def failure(type = nil)
|
17
|
+
return if @result.success? || !undefined_output?
|
18
|
+
|
19
|
+
set_output(yield(@result)) if result_type?(type)
|
20
|
+
end
|
21
|
+
|
22
|
+
def success(type = nil)
|
23
|
+
return if @result.failure? || !undefined_output?
|
24
|
+
|
25
|
+
set_output(yield(@result)) if result_type?(type)
|
26
|
+
end
|
27
|
+
|
28
|
+
def unknown
|
29
|
+
@output = yield(@result) if @__is_unknown && undefined_output?
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def set_output(value)
|
35
|
+
@__is_unknown = false
|
36
|
+
|
37
|
+
@output = value
|
38
|
+
end
|
39
|
+
|
40
|
+
def undefined_output?
|
41
|
+
::Kind::Undefined == @output
|
42
|
+
end
|
43
|
+
|
44
|
+
def result_type?(type)
|
45
|
+
type.nil? || @result.type == type
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/micro/case/safe.rb
CHANGED
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,15 @@ 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
|
+
result_wrapper = ::Micro::Case::Result::Wrapper.new(result)
|
43
|
+
|
44
|
+
yield(result_wrapper)
|
45
|
+
|
46
|
+
result_wrapper.output
|
40
47
|
end
|
41
48
|
|
42
49
|
alias __call__ call
|
@@ -68,17 +75,23 @@ module Micro
|
|
68
75
|
raise Case::Error::InvalidInvocationOfTheThenMethod.new("#{self.class.name}#")
|
69
76
|
end
|
70
77
|
|
71
|
-
def
|
72
|
-
use_case
|
78
|
+
def __call_use_case(use_case, result, input)
|
79
|
+
__build_use_case(use_case, result, input).__call__
|
73
80
|
end
|
74
81
|
|
75
82
|
def __call_next_use_cases(first_result)
|
76
83
|
@next_ones.reduce(first_result) do |result, use_case|
|
77
84
|
break result if result.failure?
|
78
85
|
|
79
|
-
|
86
|
+
__call_use_case(use_case, result, result.data)
|
80
87
|
end
|
81
88
|
end
|
89
|
+
|
90
|
+
def __build_use_case(use_case, result, input)
|
91
|
+
return use_case.__new__(result, input) unless use_case.is_a?(Array)
|
92
|
+
|
93
|
+
use_case[0].__new__(result, input.merge(use_case[1]))
|
94
|
+
end
|
82
95
|
end
|
83
96
|
end
|
84
97
|
end
|