u-case 3.0.0.rc7 → 4.0.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,31 +8,36 @@ 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'
16
16
 
17
17
  require 'micro/cases'
18
18
 
19
- include Micro::Attributes.without(:strict_initialize)
19
+ include Micro::Attributes.with(:initialize, :diff)
20
20
 
21
21
  def self.call(options = Kind::Empty::HASH)
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
@@ -58,7 +63,8 @@ module Micro
58
63
  end
59
64
 
60
65
  def self.inherited(subclass)
61
- subclass.attributes(self.attributes_data({}))
66
+ subclass.__attributes_set_after_inherit__(self.__attributes_data__)
67
+
62
68
  subclass.extend ::Micro::Attributes.const_get('Macros::ForSubclasses'.freeze)
63
69
 
64
70
  if self.send(:__flow_use_cases) && !subclass.name.to_s.end_with?(FLOW_STEP)
@@ -70,11 +76,9 @@ module Micro
70
76
  end
71
77
 
72
78
  def self.__new__(result, arg)
73
- input = result.__set_transitions_accessible_attributes__(arg)
79
+ input = result.__set_accessible_attributes__(arg)
74
80
 
75
- instance = new(input)
76
- instance.__set_result__(result)
77
- instance
81
+ new(input).__set_result__(result)
78
82
  end
79
83
 
80
84
  def self.__flow_builder__
@@ -127,7 +131,7 @@ module Micro
127
131
  end
128
132
 
129
133
  def __call__
130
- __call!
134
+ call
131
135
  end
132
136
 
133
137
  def __set_result__(result)
@@ -135,12 +139,20 @@ module Micro
135
139
  raise Error::ResultIsAlreadyDefined if defined?(@__result)
136
140
 
137
141
  @__result = result
142
+
143
+ self
138
144
  end
139
145
 
140
146
  private
141
147
 
142
- # This method was reserved for a new feature
148
+ def apply(name)
149
+ method(name)
150
+ end
151
+
143
152
  def call
153
+ return __call_use_case_flow if __call_use_case_flow?
154
+
155
+ __call_use_case
144
156
  end
145
157
 
146
158
  def __setup_use_case(input)
@@ -151,12 +163,6 @@ module Micro
151
163
  self.attributes = input
152
164
  end
153
165
 
154
- def __call!
155
- return __call_use_case_flow if __call_use_case_flow?
156
-
157
- __call_use_case
158
- end
159
-
160
166
  def __call_use_case
161
167
  result = call!
162
168
 
@@ -203,7 +209,7 @@ module Micro
203
209
  __result.__set__(is_success, value, type, self)
204
210
  end
205
211
 
206
- private_constant :MapFailureType
212
+ private_constant :MapFailureType, :INVALID_INVOCATION_OF_THE_THEN_METHOD
207
213
  end
208
214
 
209
215
  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,11 +46,16 @@ 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)
53
- exception.is_a?(InvalidResult) || exception.is_a?(UnexpectedResult) || exception.is_a?(ArgumentError)
55
+ case exception
56
+ when Kind::Error, ArgumentError, InvalidResult, UnexpectedResult then true
57
+ else false
58
+ end
54
59
  end
55
60
  end
56
61
  end
@@ -5,24 +5,41 @@ 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 = Transitions::MapEverything)
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 if enable_transitions
20
33
  end
21
34
 
22
35
  def to_ary
23
36
  [data, type]
24
37
  end
25
38
 
39
+ def to_sym
40
+ @__success ? :success : :failure
41
+ end
42
+
26
43
  def [](key)
27
44
  data[key]
28
45
  end
@@ -44,13 +61,17 @@ module Micro
44
61
  end
45
62
 
46
63
  def success?
47
- @success
64
+ @__success
48
65
  end
49
66
 
50
67
  def failure?
51
68
  !success?
52
69
  end
53
70
 
71
+ def accessible_attributes
72
+ @__accessible_attributes.keys
73
+ end
74
+
54
75
  def on_success(expected_type = nil)
55
76
  return self unless __success_type?(expected_type)
56
77
 
@@ -85,7 +106,7 @@ module Micro
85
106
  can_yield_self = respond_to?(:yield_self)
86
107
 
87
108
  if block
88
- raise Error::InvalidInvocationOfTheThenMethod if use_case
109
+ raise INVALID_INVOCATION_OF_THE_THEN_METHOD if use_case
89
110
  raise NotImplementedError if !can_yield_self
90
111
 
91
112
  yield_self(&block)
@@ -94,7 +115,7 @@ module Micro
94
115
  return failure? ? self : __call_proc(use_case, 'then(-> {})'.freeze) if use_case.is_a?(Proc)
95
116
  return failure? ? self : __call_method(use_case, attributes) if use_case.is_a?(Method)
96
117
 
97
- raise Error::InvalidInvocationOfTheThenMethod unless ::Micro.case_or_flow?(use_case)
118
+ raise INVALID_INVOCATION_OF_THE_THEN_METHOD unless ::Micro.case_or_flow?(use_case)
98
119
 
99
120
  return self if failure?
100
121
 
@@ -114,13 +135,13 @@ module Micro
114
135
  return __call_proc(arg, '| -> {}'.freeze) if arg.is_a?(Proc)
115
136
  return __call_method(arg) if arg.is_a?(Method)
116
137
 
117
- raise Error::InvalidInvocationOfTheThenMethod unless ::Micro.case_or_flow?(arg)
138
+ raise INVALID_INVOCATION_OF_THE_THEN_METHOD unless ::Micro.case_or_flow?(arg)
118
139
 
119
140
  failure? ? self : arg.__new__(self, data).__call__
120
141
  end
121
142
 
122
143
  def transitions
123
- @__transitions.clone
144
+ @__transitions.dup
124
145
  end
125
146
 
126
147
  FetchData = -> (data) do
@@ -134,42 +155,46 @@ module Micro
134
155
  raise Error::InvalidResultType unless type.is_a?(Symbol)
135
156
  raise Error::InvalidUseCase unless use_case.is_a?(::Micro::Case)
136
157
 
137
- @success, @type, @use_case = is_success, type, use_case
158
+ @__success, @type, @use_case = is_success, type, use_case
138
159
 
139
- @data = FetchData.call(data)
160
+ @data = FetchData.call(data).freeze
140
161
 
141
162
  raise Micro::Case::Error::InvalidResult.new(is_success, type, use_case) unless @data
142
163
 
143
- @__transitions_accumulated_data.merge!(@data)
164
+ @__accumulated_data.merge!(@data)
165
+
166
+ use_case_attributes = Utils.symbolize_hash_keys(@use_case.attributes)
144
167
 
145
- __set_transition if @@transition_tracking_enabled
168
+ __update_accessible_attributes(use_case_attributes)
169
+
170
+ __set_transition(use_case_attributes) unless @__transitions.frozen?
146
171
 
147
172
  self
148
173
  end
149
174
 
150
- def __set_transitions_accessible_attributes__(arg)
151
- return arg unless @@transition_tracking_enabled
175
+ def __set_accessible_attributes__(arg)
176
+ return arg unless arg.is_a?(Hash)
152
177
 
153
- if arg.is_a?(Hash)
154
- attributes = Utils.symbolize_hash_keys(arg)
178
+ attributes = Utils.symbolize_hash_keys(arg)
155
179
 
156
- __update_transitions_accessible_attributes(attributes)
157
- end
180
+ __update_accessible_attributes(attributes)
181
+ __fetch_accessible_attributes
158
182
  end
159
183
 
160
184
  private
161
185
 
162
- def __call_with_accumulated_data(fn, opt = nil)
163
- input =
164
- __update_transitions_accessible_attributes(
165
- opt ? opt.merge(@__transitions_accumulated_data) : @__transitions_accumulated_data
166
- )
186
+ def __update_accessible_attributes(attributes)
187
+ @__accessible_attributes.merge!(attributes)
188
+ end
167
189
 
168
- fn.arity.zero? ? fn.call : fn.call(input)
190
+ def __fetch_accessible_attributes
191
+ @__accessible_attributes.dup
169
192
  end
170
193
 
171
194
  def __call_proc(fn, expected)
172
- result = __call_with_accumulated_data(fn)
195
+ __update_accessible_attributes(@__accumulated_data)
196
+
197
+ result = fn.arity.zero? ? fn.call : fn.call(__fetch_accessible_attributes)
173
198
 
174
199
  return self if result === self
175
200
 
@@ -177,7 +202,9 @@ module Micro
177
202
  end
178
203
 
179
204
  def __call_method(methd, attributes = nil)
180
- result = __call_with_accumulated_data(methd, attributes)
205
+ __update_accessible_attributes(attributes ? attributes.merge(@__accumulated_data) : @__accumulated_data)
206
+
207
+ result = methd.arity.zero? ? methd.call : methd.call(**__fetch_accessible_attributes)
181
208
 
182
209
  return self if result === self
183
210
 
@@ -192,27 +219,11 @@ module Micro
192
219
  failure? && (expected_type.nil? || expected_type == type)
193
220
  end
194
221
 
195
- def __update_transitions_accessible_attributes(attributes)
196
- @__transitions_accessible_attributes.merge!(attributes)
197
- @__transitions_accessible_attributes
198
- end
199
-
200
- def __set_transition
201
- use_case_class = @use_case.class
202
- use_case_attributes = Utils.symbolize_hash_keys(@use_case.attributes)
203
-
204
- __update_transitions_accessible_attributes(use_case_attributes)
205
-
206
- result = @success ? :success : :failure
207
-
208
- @__transitions << {
209
- use_case: { class: use_case_class, attributes: use_case_attributes },
210
- result => { type: @type, result: data },
211
- accessible_attributes: @__transitions_accessible_attributes.keys
212
- }
222
+ def __set_transition(use_case_attributes)
223
+ @__transitions << @__transitions_mapper.call(self, use_case_attributes)
213
224
  end
214
225
 
215
- private_constant :FetchData
226
+ private_constant :FetchData, :INVALID_INVOCATION_OF_THE_THEN_METHOD
216
227
  end
217
228
  end
218
229
  end
@@ -0,0 +1,18 @@
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
+ {
9
+ use_case: { class: result.use_case.class, attributes: use_case_attributes },
10
+ result.to_sym => { type: result.type, result: result.data },
11
+ accessible_attributes: result.accessible_attributes
12
+ }
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+
@@ -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
 
@@ -3,10 +3,10 @@
3
3
  module Micro
4
4
  class Case
5
5
  class Strict < ::Micro::Case
6
- include Micro::Attributes::Features::StrictInitialize
6
+ include Micro::Attributes::Features::Initialize::Strict
7
7
 
8
8
  class Safe < ::Micro::Case::Safe
9
- include Micro::Attributes::Features::StrictInitialize
9
+ include Micro::Attributes::Features::Initialize::Strict
10
10
  end
11
11
  end
12
12
  end
@@ -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.rc7'.freeze
5
+ VERSION = '4.0.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