u-case 3.0.0.rc6 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,8 +8,8 @@ require 'micro/case/version'
8
8
  module Micro
9
9
  class Case
10
10
  require 'micro/case/utils'
11
- require 'micro/case/result'
12
11
  require 'micro/case/error'
12
+ require 'micro/case/result'
13
13
  require 'micro/case/safe'
14
14
  require 'micro/case/strict'
15
15
  require 'micro/case/config'
@@ -22,17 +22,22 @@ module Micro
22
22
  new(options).__call__
23
23
  end
24
24
 
25
+ INVALID_INVOCATION_OF_THE_THEN_METHOD =
26
+ Error::InvalidInvocationOfTheThenMethod.new("#{self.name}.")
27
+
25
28
  def self.then(use_case = nil, &block)
26
29
  can_yield_self = respond_to?(:yield_self)
27
30
 
28
31
  if block
29
- raise Error::InvalidInvocationOfTheThenMethod if use_case
32
+ raise INVALID_INVOCATION_OF_THE_THEN_METHOD if use_case
30
33
  raise NotImplementedError if !can_yield_self
31
34
 
32
35
  yield_self(&block)
33
36
  else
34
37
  return yield_self if !use_case && can_yield_self
35
38
 
39
+ raise INVALID_INVOCATION_OF_THE_THEN_METHOD unless ::Micro.case_or_flow?(use_case)
40
+
36
41
  self.call.then(use_case)
37
42
  end
38
43
  end
@@ -70,11 +75,9 @@ module Micro
70
75
  end
71
76
 
72
77
  def self.__new__(result, arg)
73
- input = result.__set_transitions_accessible_attributes__(arg)
78
+ input = result.__set_accessible_attributes__(arg)
74
79
 
75
- instance = new(input)
76
- instance.__set_result__(result)
77
- instance
80
+ new(input).__set_result__(result)
78
81
  end
79
82
 
80
83
  def self.__flow_builder__
@@ -127,7 +130,7 @@ module Micro
127
130
  end
128
131
 
129
132
  def __call__
130
- __call!
133
+ call
131
134
  end
132
135
 
133
136
  def __set_result__(result)
@@ -135,12 +138,20 @@ module Micro
135
138
  raise Error::ResultIsAlreadyDefined if defined?(@__result)
136
139
 
137
140
  @__result = result
141
+
142
+ self
138
143
  end
139
144
 
140
145
  private
141
146
 
142
- # This method was reserved for a new feature
147
+ def apply(name)
148
+ method(name)
149
+ end
150
+
143
151
  def call
152
+ return __call_use_case_flow if __call_use_case_flow?
153
+
154
+ __call_use_case
144
155
  end
145
156
 
146
157
  def __setup_use_case(input)
@@ -151,12 +162,6 @@ module Micro
151
162
  self.attributes = input
152
163
  end
153
164
 
154
- def __call!
155
- return __call_use_case_flow if __call_use_case_flow?
156
-
157
- __call_use_case
158
- end
159
-
160
165
  def __call_use_case
161
166
  result = call!
162
167
 
@@ -203,7 +208,7 @@ module Micro
203
208
  __result.__set__(is_success, value, type, self)
204
209
  end
205
210
 
206
- private_constant :MapFailureType
211
+ private_constant :MapFailureType, :INVALID_INVOCATION_OF_THE_THEN_METHOD
207
212
  end
208
213
 
209
214
  def self.case_or_flow?(arg)
@@ -7,16 +7,28 @@ module Micro
7
7
  class Config
8
8
  include Singleton
9
9
 
10
+ def enable_transitions=(value)
11
+ Micro::Case::Result.class_variable_set(
12
+ :@@transitions_enabled, Kind::Of::Boolean(value)
13
+ )
14
+ end
15
+
10
16
  def enable_activemodel_validation=(value)
11
17
  return unless Kind::Of::Boolean(value)
12
18
 
13
19
  require 'micro/case/with_activemodel_validation'
14
20
  end
15
21
 
16
- def enable_transitions=(value)
17
- Micro::Case::Result.class_variable_set(
18
- :@@transition_tracking_enabled, Kind::Of::Boolean(value)
19
- )
22
+ def set_activemodel_validation_errors_failure=(value)
23
+ return unless value
24
+
25
+ @activemodel_validation_errors_failure = Kind.of(Symbol, value)
26
+ end
27
+
28
+ def activemodel_validation_errors_failure
29
+ return @activemodel_validation_errors_failure if defined?(@activemodel_validation_errors_failure)
30
+
31
+ @activemodel_validation_errors_failure = :invalid_attributes
20
32
  end
21
33
  end
22
34
  end
@@ -46,7 +46,9 @@ module Micro
46
46
  end
47
47
 
48
48
  class InvalidInvocationOfTheThenMethod < StandardError
49
- def initialize; super('Invalid invocation of the Micro::Case::Result#then method'); end
49
+ def initialize(class_name)
50
+ super("Invalid invocation of the #{class_name}then method")
51
+ end
50
52
  end
51
53
 
52
54
  def self.by_wrong_usage?(exception)
@@ -5,18 +5,31 @@ require 'set'
5
5
  module Micro
6
6
  class Case
7
7
  class Result
8
+ require 'micro/case/result/transitions'
9
+
8
10
  Kind::Types.add(self)
9
11
 
10
- @@transition_tracking_enabled = true
12
+ INVALID_INVOCATION_OF_THE_THEN_METHOD =
13
+ Error::InvalidInvocationOfTheThenMethod.new("#{self.name}#")
14
+
15
+ @@transitions_enabled = true
16
+
17
+ def self.transitions_enabled?
18
+ @@transitions_enabled
19
+ end
11
20
 
12
21
  attr_reader :type, :data, :use_case
13
22
 
14
23
  alias value data
15
24
 
16
- def initialize
17
- @__transitions = []
18
- @__transitions_accumulated_data = {}
19
- @__transitions_accessible_attributes = {}
25
+ def initialize(transitions_mapper = nil)
26
+ @__accumulated_data = {}
27
+ @__accessible_attributes = {}
28
+
29
+ enable_transitions = @@transitions_enabled
30
+
31
+ @__transitions = enable_transitions ? [] : Kind::Empty::ARRAY
32
+ @__transitions_mapper = transitions_mapper || Transitions::MapEverything if enable_transitions
20
33
  end
21
34
 
22
35
  def to_ary
@@ -44,13 +57,17 @@ module Micro
44
57
  end
45
58
 
46
59
  def success?
47
- @success
60
+ @__success
48
61
  end
49
62
 
50
63
  def failure?
51
64
  !success?
52
65
  end
53
66
 
67
+ def accessible_attributes
68
+ @__accessible_attributes.keys
69
+ end
70
+
54
71
  def on_success(expected_type = nil)
55
72
  return self unless __success_type?(expected_type)
56
73
 
@@ -85,7 +102,7 @@ module Micro
85
102
  can_yield_self = respond_to?(:yield_self)
86
103
 
87
104
  if block
88
- raise Error::InvalidInvocationOfTheThenMethod if use_case
105
+ raise INVALID_INVOCATION_OF_THE_THEN_METHOD if use_case
89
106
  raise NotImplementedError if !can_yield_self
90
107
 
91
108
  yield_self(&block)
@@ -94,7 +111,7 @@ module Micro
94
111
  return failure? ? self : __call_proc(use_case, 'then(-> {})'.freeze) if use_case.is_a?(Proc)
95
112
  return failure? ? self : __call_method(use_case, attributes) if use_case.is_a?(Method)
96
113
 
97
- raise Error::InvalidInvocationOfTheThenMethod unless ::Micro.case_or_flow?(use_case)
114
+ raise INVALID_INVOCATION_OF_THE_THEN_METHOD unless ::Micro.case_or_flow?(use_case)
98
115
 
99
116
  return self if failure?
100
117
 
@@ -114,13 +131,13 @@ module Micro
114
131
  return __call_proc(arg, '| -> {}'.freeze) if arg.is_a?(Proc)
115
132
  return __call_method(arg) if arg.is_a?(Method)
116
133
 
117
- raise Error::InvalidInvocationOfTheThenMethod unless ::Micro.case_or_flow?(arg)
134
+ raise INVALID_INVOCATION_OF_THE_THEN_METHOD unless ::Micro.case_or_flow?(arg)
118
135
 
119
136
  failure? ? self : arg.__new__(self, data).__call__
120
137
  end
121
138
 
122
139
  def transitions
123
- @__transitions.clone
140
+ @__transitions.dup
124
141
  end
125
142
 
126
143
  FetchData = -> (data) do
@@ -134,44 +151,46 @@ module Micro
134
151
  raise Error::InvalidResultType unless type.is_a?(Symbol)
135
152
  raise Error::InvalidUseCase unless use_case.is_a?(::Micro::Case)
136
153
 
137
- @success, @type, @use_case = is_success, type, use_case
154
+ @__success, @type, @use_case = is_success, type, use_case
138
155
 
139
- @data = FetchData.call(data)
156
+ @data = FetchData.call(data).freeze
140
157
 
141
158
  raise Micro::Case::Error::InvalidResult.new(is_success, type, use_case) unless @data
142
159
 
143
- if @@transition_tracking_enabled
144
- @__transitions_accumulated_data.merge!(@data)
160
+ @__accumulated_data.merge!(@data)
145
161
 
146
- __set_transition
147
- end
162
+ use_case_attributes = Utils.symbolize_hash_keys(@use_case.attributes)
163
+
164
+ __update_accessible_attributes(use_case_attributes)
165
+
166
+ __set_transition(use_case_attributes) unless @__transitions.frozen?
148
167
 
149
168
  self
150
169
  end
151
170
 
152
- def __set_transitions_accessible_attributes__(arg)
153
- return arg unless @@transition_tracking_enabled
171
+ def __set_accessible_attributes__(arg)
172
+ return arg unless arg.is_a?(Hash)
154
173
 
155
- if arg.is_a?(Hash)
156
- attributes = Utils.symbolize_hash_keys(arg)
174
+ attributes = Utils.symbolize_hash_keys(arg)
157
175
 
158
- __update_transitions_accessible_attributes(attributes)
159
- end
176
+ __update_accessible_attributes(attributes)
177
+ __fetch_accessible_attributes
160
178
  end
161
179
 
162
180
  private
163
181
 
164
- def __call_with_accumulated_data(fn, opt = nil)
165
- input =
166
- __update_transitions_accessible_attributes(
167
- opt ? opt.merge(@__transitions_accumulated_data) : @__transitions_accumulated_data
168
- )
182
+ def __update_accessible_attributes(attributes)
183
+ @__accessible_attributes.merge!(attributes)
184
+ end
169
185
 
170
- fn.arity.zero? ? fn.call : fn.call(input)
186
+ def __fetch_accessible_attributes
187
+ @__accessible_attributes.dup
171
188
  end
172
189
 
173
190
  def __call_proc(fn, expected)
174
- result = __call_with_accumulated_data(fn)
191
+ __update_accessible_attributes(@__accumulated_data)
192
+
193
+ result = fn.arity.zero? ? fn.call : fn.call(__fetch_accessible_attributes)
175
194
 
176
195
  return self if result === self
177
196
 
@@ -179,7 +198,9 @@ module Micro
179
198
  end
180
199
 
181
200
  def __call_method(methd, attributes = nil)
182
- result = __call_with_accumulated_data(methd, attributes)
201
+ __update_accessible_attributes(attributes ? attributes.merge(@__accumulated_data) : @__accumulated_data)
202
+
203
+ result = methd.arity.zero? ? methd.call : methd.call(**__fetch_accessible_attributes)
183
204
 
184
205
  return self if result === self
185
206
 
@@ -194,27 +215,11 @@ module Micro
194
215
  failure? && (expected_type.nil? || expected_type == type)
195
216
  end
196
217
 
197
- def __update_transitions_accessible_attributes(attributes)
198
- @__transitions_accessible_attributes.merge!(attributes)
199
- @__transitions_accessible_attributes
200
- end
201
-
202
- def __set_transition
203
- use_case_class = @use_case.class
204
- use_case_attributes = Utils.symbolize_hash_keys(@use_case.attributes)
205
-
206
- __update_transitions_accessible_attributes(use_case_attributes)
207
-
208
- result = @success ? :success : :failure
209
-
210
- @__transitions << {
211
- use_case: { class: use_case_class, attributes: use_case_attributes },
212
- result => { type: @type, result: data },
213
- accessible_attributes: @__transitions_accessible_attributes.keys
214
- }
218
+ def __set_transition(use_case_attributes)
219
+ @__transitions << @__transitions_mapper.call(self, use_case_attributes)
215
220
  end
216
221
 
217
- private_constant :FetchData
222
+ private_constant :FetchData, :INVALID_INVOCATION_OF_THE_THEN_METHOD
218
223
  end
219
224
  end
220
225
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Micro
4
+ class Case
5
+ class Result
6
+ class Transitions
7
+ MapEverything = -> (result, use_case_attributes) do
8
+ result_track = result.success? ? :success : :failure
9
+
10
+ {
11
+ use_case: { class: result.use_case.class, attributes: use_case_attributes },
12
+ result_track => { type: result.type, result: result.data },
13
+ accessible_attributes: result.accessible_attributes
14
+ }
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+
@@ -3,12 +3,12 @@
3
3
  module Micro
4
4
  class Case
5
5
  class Safe < ::Micro::Case
6
- def self.__flow_builder
6
+ def self.__flow_builder__
7
7
  Cases::Safe::Flow
8
8
  end
9
9
 
10
10
  def __call__
11
- __call!
11
+ call
12
12
  rescue => exception
13
13
  raise exception if Error.by_wrong_usage?(exception)
14
14
 
@@ -14,6 +14,7 @@ module Micro
14
14
  end
15
15
  end
16
16
  end
17
+
17
18
  def self.slice_hash(hash, keys)
18
19
  if Kind::Of::Hash(hash).respond_to?(:slice)
19
20
  hash.slice(*keys)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Micro
4
4
  class Case
5
- VERSION = '3.0.0.rc6'.freeze
5
+ VERSION = '3.1.0'.freeze
6
6
  end
7
7
  end
@@ -37,7 +37,9 @@ module Micro
37
37
  def failure_by_validation_error(object)
38
38
  errors = object.respond_to?(:errors) ? object.errors : object
39
39
 
40
- Failure :validation_error, result: { errors: errors }
40
+ Failure Micro::Case::Config.instance.activemodel_validation_errors_failure, result: {
41
+ errors: errors
42
+ }
41
43
  end
42
44
  end
43
45
  end
@@ -10,9 +10,7 @@ module Micro
10
10
  attr_reader :use_cases
11
11
 
12
12
  def self.map_use_cases(arg)
13
- return arg.use_cases if arg.is_a?(Flow)
14
-
15
- Array(arg)
13
+ arg.is_a?(Flow) ? arg.use_cases : Array(arg)
16
14
  end
17
15
 
18
16
  def self.build(args)
@@ -24,17 +22,17 @@ module Micro
24
22
  end
25
23
 
26
24
  def initialize(use_cases)
27
- @use_cases = use_cases
28
- @first_use_case = use_cases[0]
29
- @next_use_cases = use_cases[1..-1]
25
+ @use_cases = use_cases.dup.freeze
26
+ @next_ones = use_cases.dup
27
+ @first = @next_ones.shift
30
28
  end
31
29
 
32
30
  def call!(input:, result:)
33
- first_result = __next_use_case_result(@first_use_case, result, input)
31
+ first_result = __case_use_case(@first, result, input)
34
32
 
35
- return first_result if @next_use_cases.empty?
33
+ return first_result if @next_ones.empty?
36
34
 
37
- __next_use_cases_result(first_result)
35
+ __call_next_use_cases(first_result)
38
36
  end
39
37
 
40
38
  def call(input = Kind::Empty::HASH)
@@ -51,28 +49,34 @@ module Micro
51
49
  can_yield_self = respond_to?(:yield_self)
52
50
 
53
51
  if block
54
- raise Error::InvalidInvocationOfTheThenMethod if use_case
52
+ raise_invalid_invocation_of_the_then_method if use_case
55
53
  raise NotImplementedError if !can_yield_self
56
54
 
57
55
  yield_self(&block)
58
56
  else
59
57
  return yield_self if !use_case && can_yield_self
60
58
 
59
+ raise_invalid_invocation_of_the_then_method unless ::Micro.case_or_flow?(use_case)
60
+
61
61
  self.call.then(use_case)
62
62
  end
63
63
  end
64
64
 
65
65
  private
66
66
 
67
- def __next_use_case_result(use_case, result, input)
67
+ def raise_invalid_invocation_of_the_then_method
68
+ raise Case::Error::InvalidInvocationOfTheThenMethod.new("#{self.class.name}#")
69
+ end
70
+
71
+ def __case_use_case(use_case, result, input)
68
72
  use_case.__new__(result, input).__call__
69
73
  end
70
74
 
71
- def __next_use_cases_result(first_result)
72
- @next_use_cases.reduce(first_result) do |result, use_case|
75
+ def __call_next_use_cases(first_result)
76
+ @next_ones.reduce(first_result) do |result, use_case|
73
77
  break result if result.failure?
74
78
 
75
- __next_use_case_result(use_case, result, result.data)
79
+ __case_use_case(use_case, result, result.data)
76
80
  end
77
81
  end
78
82
  end