u-case 2.4.0 → 3.0.0.rc3

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.
@@ -3,12 +3,16 @@
3
3
  module Micro
4
4
  class Case
5
5
  class Safe < ::Micro::Case
6
+ def self.__flow_builder
7
+ Cases::Safe::Flow
8
+ end
9
+
6
10
  def call
7
11
  __call
8
12
  rescue => exception
9
- raise exception if Error::ByWrongUsage.check(exception)
13
+ raise exception if Error.by_wrong_usage?(exception)
10
14
 
11
- Failure(exception)
15
+ Failure(result: exception)
12
16
  end
13
17
  end
14
18
  end
@@ -3,8 +3,8 @@
3
3
  module Micro
4
4
  class Case
5
5
  module Utils
6
- def self.symbolize_keys(hash)
7
- if Kind.of.Hash(hash).respond_to?(:transform_keys)
6
+ def self.symbolize_hash_keys(hash)
7
+ if Kind::Of::Hash(hash).respond_to?(:transform_keys)
8
8
  hash.transform_keys { |key| key.to_sym rescue key }
9
9
  else
10
10
  hash.each_with_object({}) do |(k, v), memo|
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Micro
4
4
  class Case
5
- VERSION = '2.4.0'.freeze
5
+ VERSION = '3.0.0.rc3'.freeze
6
6
  end
7
7
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'kind/active_model/validation'
4
+
3
5
  require 'micro/case'
4
6
 
5
7
  module Micro
@@ -35,7 +37,7 @@ module Micro
35
37
  def failure_by_validation_error(object)
36
38
  errors = object.respond_to?(:errors) ? object.errors : object
37
39
 
38
- Failure(:validation_error) { { errors: errors } }
40
+ Failure :validation_error, result: { errors: errors }
39
41
  end
40
42
  end
41
43
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'micro/cases/flow'
4
+ require 'micro/cases/safe/flow'
5
+
6
+ module Micro
7
+ module Cases
8
+ def self.flow(args)
9
+ Flow.build(args)
10
+ end
11
+
12
+ def self.safe_flow(args)
13
+ Safe::Flow.build(args)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Micro
4
+ module Cases
5
+ class Flow
6
+ class InvalidUseCases < ArgumentError
7
+ def initialize; super('argument must be a collection of `Micro::Case` classes'.freeze); end
8
+ end
9
+
10
+ attr_reader :use_cases
11
+
12
+ def self.map_use_cases(arg)
13
+ return arg.use_cases if arg.is_a?(Flow)
14
+
15
+ Array(arg)
16
+ end
17
+
18
+ def self.build(args)
19
+ use_cases = Array(args).flat_map { |arg| map_use_cases(arg) }
20
+
21
+ raise InvalidUseCases if use_cases.any? { |klass| !(klass < ::Micro::Case) }
22
+
23
+ new(use_cases)
24
+ end
25
+
26
+ def initialize(use_cases)
27
+ @use_cases = use_cases
28
+ @first_use_case = use_cases[0]
29
+ @next_use_cases = use_cases[1..-1]
30
+ end
31
+
32
+ def call(arg = {})
33
+ memo = arg.is_a?(Hash) ? arg.dup : {}
34
+
35
+ first_result = first_use_case_result(arg)
36
+
37
+ return first_result if @next_use_cases.empty?
38
+
39
+ next_use_cases_result(first_result, memo)
40
+ end
41
+
42
+ def to_proc
43
+ Proc.new { |arg| call(arg) }
44
+ end
45
+
46
+ private
47
+
48
+ def is_a_result?(arg)
49
+ arg.is_a?(Case::Result)
50
+ end
51
+
52
+ def arg_to_call?(arg)
53
+ return true if arg.is_a?(::Micro::Case) || arg.is_a?(Flow)
54
+ return true if arg.is_a?(Class) && arg < ::Micro::Case
55
+ return false
56
+ end
57
+
58
+ def call_arg(arg)
59
+ output = arg.call
60
+
61
+ is_a_result?(output) ? output.value : output
62
+ end
63
+
64
+ def first_use_case_input(arg)
65
+ return call_arg(arg) if arg_to_call?(arg)
66
+ return arg.value if is_a_result?(arg)
67
+
68
+ arg
69
+ end
70
+
71
+ def first_use_case_result(arg)
72
+ input = first_use_case_input(arg)
73
+
74
+ result = Case::Result.new
75
+
76
+ @first_use_case.__call_and_set_transition__(result, input)
77
+ end
78
+
79
+ def next_use_case_result(use_case, result, input)
80
+ use_case.__new__(result, input).call
81
+ end
82
+
83
+ def next_use_cases_result(first_result, memo)
84
+ @next_use_cases.reduce(first_result) do |result, use_case|
85
+ break result if result.failure?
86
+
87
+ memo.merge!(result.value)
88
+
89
+ result.__set_transitions_accessible_attributes__(memo)
90
+
91
+ next_use_case_result(use_case, result, memo)
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Micro
4
+ module Cases
5
+ module Safe
6
+ class Flow < Cases::Flow
7
+ private def next_use_case_result(use_case, result, input)
8
+ instance = use_case.__new__(result, input)
9
+ instance.call
10
+ rescue => exception
11
+ raise exception if Case::Error.by_wrong_usage?(exception)
12
+
13
+ result.__set__(false, exception, :exception, instance)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,5 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'kind/active_model/validation'
4
-
5
3
  require 'micro/case/with_activemodel_validation'
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
25
25
 
26
26
  spec.required_ruby_version = '>= 2.2.0'
27
27
 
28
- spec.add_runtime_dependency 'kind', '~> 3.0'
28
+ spec.add_runtime_dependency 'kind', '>= 3.0', '< 5.0'
29
29
  spec.add_runtime_dependency 'u-attributes', '~> 1.1'
30
30
 
31
31
  spec.add_development_dependency 'bundler'
metadata CHANGED
@@ -1,29 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: u-case
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 3.0.0.rc3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rodrigo Serradura
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-06-26 00:00:00.000000000 Z
11
+ date: 2020-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: kind
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '3.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '5.0'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
25
28
  - !ruby/object:Gem::Version
26
29
  version: '3.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.0'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: u-attributes
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -85,19 +91,19 @@ files:
85
91
  - bin/console
86
92
  - bin/setup
87
93
  - lib/micro/case.rb
94
+ - lib/micro/case/config.rb
88
95
  - lib/micro/case/error.rb
89
- - lib/micro/case/flow.rb
90
- - lib/micro/case/flow/reducer.rb
91
96
  - lib/micro/case/result.rb
92
97
  - lib/micro/case/safe.rb
93
- - lib/micro/case/safe/flow.rb
94
98
  - lib/micro/case/strict.rb
95
99
  - lib/micro/case/utils.rb
96
100
  - lib/micro/case/version.rb
97
101
  - lib/micro/case/with_activemodel_validation.rb
102
+ - lib/micro/cases.rb
103
+ - lib/micro/cases/flow.rb
104
+ - lib/micro/cases/safe/flow.rb
98
105
  - lib/u-case.rb
99
106
  - lib/u-case/with_activemodel_validation.rb
100
- - lib/u-case/with_validation.rb
101
107
  - test.sh
102
108
  - u-case.gemspec
103
109
  homepage: https://github.com/serradura/u-case
@@ -115,9 +121,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
115
121
  version: 2.2.0
116
122
  required_rubygems_version: !ruby/object:Gem::Requirement
117
123
  requirements:
118
- - - ">="
124
+ - - ">"
119
125
  - !ruby/object:Gem::Version
120
- version: '0'
126
+ version: 1.3.1
121
127
  requirements: []
122
128
  rubygems_version: 3.0.6
123
129
  signing_key:
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Micro
4
- class Case
5
- module Flow
6
- module ClassMethods
7
- def __flow__
8
- return @__flow if defined?(@__flow)
9
- end
10
-
11
- def flow(*args)
12
- @__flow = flow_reducer.build(args)
13
- end
14
-
15
- def call(options = {})
16
- new(options).call
17
- end
18
- end
19
-
20
- CONSTRUCTOR = <<-RUBY
21
- def initialize(options)
22
- @options = options
23
-
24
- flow = self.class.__flow__
25
-
26
- raise Error::UndefinedFlow unless flow
27
- end
28
- RUBY
29
-
30
- private_constant :ClassMethods, :CONSTRUCTOR
31
-
32
- # Deprecated: Classes with flows are now defined via `Micro::Case` inheritance
33
- def self.included(base)
34
- warn 'Deprecation: Micro::Case::Flow mixin is being deprecated, please use `Micro::Case` inheritance instead.'
35
-
36
- def base.flow_reducer; Reducer; end
37
-
38
- base.extend(ClassMethods)
39
-
40
- base.class_eval(CONSTRUCTOR)
41
- end
42
-
43
- def call
44
- self.class.__flow__.call(@options)
45
- end
46
- end
47
- end
48
- end
@@ -1,104 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Micro
4
- class Case
5
- module Flow
6
- class Reducer
7
- attr_reader :use_cases
8
-
9
- def self.map_use_cases(arg)
10
- return arg.use_cases if arg.is_a?(Reducer)
11
- return arg.__flow__.use_cases if arg.is_a?(Class) && arg < ::Micro::Case::Flow
12
-
13
- Array(arg)
14
- end
15
-
16
- def self.build(args)
17
- use_cases = Array(args).flat_map { |arg| map_use_cases(arg) }
18
-
19
- raise Error::InvalidUseCases if use_cases.any? { |klass| !(klass < ::Micro::Case) }
20
-
21
- new(use_cases)
22
- end
23
-
24
- def initialize(use_cases)
25
- @use_cases = use_cases
26
- @first_use_case = use_cases[0]
27
- @next_use_cases = use_cases[1..-1]
28
- end
29
-
30
- def call(arg = {})
31
- memo = arg.is_a?(Hash) ? arg.dup : {}
32
-
33
- first_result = first_use_case_result(arg)
34
-
35
- return first_result if @next_use_cases.empty?
36
-
37
- next_use_cases_result(first_result, memo)
38
- end
39
-
40
- def >>(arg)
41
- self.class.build(use_cases + self.class.map_use_cases(arg))
42
- end
43
-
44
- def &(arg)
45
- raise NoMethodError, "undefined method `&' for #{self.inspect}. Please, use the method `>>' to avoid this error."
46
- end
47
-
48
- def to_proc
49
- Proc.new { |arg| call(arg) }
50
- end
51
-
52
- private
53
-
54
- def is_a_result?(arg)
55
- arg.is_a?(Micro::Case::Result)
56
- end
57
-
58
- def arg_to_call?(arg)
59
- return true if arg.is_a?(::Micro::Case) || arg.is_a?(Reducer)
60
- return true if arg.is_a?(Class) && (arg < ::Micro::Case || arg < ::Micro::Case::Flow)
61
- return false
62
- end
63
-
64
- def call_arg(arg)
65
- output = arg.call
66
-
67
- is_a_result?(output) ? output.value : output
68
- end
69
-
70
- def first_use_case_input(arg)
71
- return call_arg(arg) if arg_to_call?(arg)
72
- return arg.value if is_a_result?(arg)
73
-
74
- arg
75
- end
76
-
77
- def first_use_case_result(arg)
78
- input = first_use_case_input(arg)
79
-
80
- result = ::Micro::Case::Result.new
81
-
82
- @first_use_case.__call_and_set_transition__(result, input)
83
- end
84
-
85
- def next_use_case_result(use_case, result, input)
86
- use_case.__new__(result, input).call
87
- end
88
-
89
- def next_use_cases_result(first_result, memo)
90
- @next_use_cases.reduce(first_result) do |result, use_case|
91
- break result if result.failure?
92
-
93
- value = result.value
94
- input = value.is_a?(Hash) ? memo.tap { |data| data.merge!(value) } : value
95
-
96
- result.__set_transitions_accessible_attributes__(memo.keys)
97
-
98
- next_use_case_result(use_case, result, input)
99
- end
100
- end
101
- end
102
- end
103
- end
104
- end
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Micro
4
- class Case
5
- class Safe
6
- module Flow
7
- def self.included(base)
8
- base.send(:include, ::Micro::Case::Flow)
9
-
10
- def base.flow_reducer; Reducer; end
11
- end
12
-
13
- class Reducer < ::Micro::Case::Flow::Reducer
14
- alias_method :&, :>>
15
-
16
- def >>(arg)
17
- raise NoMethodError, "undefined method `>>' for #{self.inspect}. Please, use the method `&' to avoid this error."
18
- end
19
-
20
- private
21
-
22
- def next_use_case_result(use_case, result, input)
23
- begin
24
- instance = use_case.__new__(result, input)
25
- instance.call
26
- rescue => exception
27
- raise exception if Error::ByWrongUsage.check(exception)
28
-
29
- result.__set__(false, exception, :exception, instance)
30
- end
31
- end
32
- end
33
- end
34
-
35
- def self.Flow(args)
36
- Flow::Reducer.build(Array(args))
37
- end
38
-
39
- def self.__flow_reducer
40
- Flow::Reducer
41
- end
42
- end
43
- end
44
- end