u-case 3.0.0.rc6 → 3.1.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.
@@ -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