u-case 2.6.0 → 3.0.0.rc5

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,12 +3,16 @@
3
3
  module Micro
4
4
  class Case
5
5
  class Safe < ::Micro::Case
6
- def call
7
- __call
6
+ def self.__flow_builder
7
+ Cases::Safe::Flow
8
+ end
9
+
10
+ def __call__
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
@@ -14,6 +14,13 @@ module Micro
14
14
  end
15
15
  end
16
16
  end
17
+ def self.slice_hash(hash, keys)
18
+ if Kind::Of::Hash(hash).respond_to?(:slice)
19
+ hash.slice(*keys)
20
+ else
21
+ hash.select { |key, _value| keys.include?(key) }
22
+ end
23
+ end
17
24
  end
18
25
  end
19
26
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Micro
4
4
  class Case
5
- VERSION = '2.6.0'.freeze
5
+ VERSION = '3.0.0.rc5'.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
@@ -29,13 +31,13 @@ module Micro
29
31
 
30
32
  return result if result.is_a?(Result)
31
33
 
32
- raise Error::UnexpectedResult.new(self.class)
34
+ raise Error::UnexpectedResult.new("#{self.class.name}#call!")
33
35
  end
34
36
 
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,86 @@
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!(input:, result:)
33
+ memo = input.is_a?(Hash) ? input.dup : Kind::Empty::HASH
34
+
35
+ first_result = @first_use_case.__call_and_set_transition__(result, input)
36
+
37
+ return first_result if @next_use_cases.empty?
38
+
39
+ __next_use_cases_result(first_result, memo)
40
+ end
41
+
42
+ def call(input = Kind::Empty::HASH)
43
+ call!(input: input, result: Case::Result.new)
44
+ end
45
+
46
+ alias __call__ call
47
+
48
+ def to_proc
49
+ Proc.new { |arg| call(arg) }
50
+ end
51
+
52
+ def then(use_case = nil, &block)
53
+ can_yield_self = respond_to?(:yield_self)
54
+
55
+ if block
56
+ raise Error::InvalidInvocationOfTheThenMethod if use_case
57
+ raise NotImplementedError if !can_yield_self
58
+
59
+ yield_self(&block)
60
+ else
61
+ return yield_self if !use_case && can_yield_self
62
+
63
+ self.call.then(use_case)
64
+ end
65
+ end
66
+
67
+ private
68
+
69
+ def __next_use_case_result(use_case, result, input)
70
+ use_case.__new__(result, input).__call__
71
+ end
72
+
73
+ def __next_use_cases_result(first_result, memo)
74
+ @next_use_cases.reduce(first_result) do |result, use_case|
75
+ break result if result.failure?
76
+
77
+ memo.merge!(result.value)
78
+
79
+ result.__set_transitions_accessible_attributes__(memo)
80
+
81
+ __next_use_case_result(use_case, result, memo)
82
+ end
83
+ end
84
+ end
85
+ end
86
+ 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'
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ['Rodrigo Serradura']
10
10
  spec.email = ['rodrigo.serradura@gmail.com']
11
11
 
12
- spec.summary = %q{Create simple and powerful use cases as objects.}
13
- spec.description = %q{Create simple and powerful use cases as objects.}
12
+ spec.summary = %q{Create simple and powerful use cases as Ruby objects.}
13
+ spec.description = %q{Create simple and powerful use cases as Ruby objects.}
14
14
  spec.homepage = 'https://github.com/serradura/u-case'
15
15
  spec.license = 'MIT'
16
16
 
@@ -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.6.0
4
+ version: 3.0.0.rc5
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-07-07 00:00:00.000000000 Z
11
+ date: 2020-08-12 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
@@ -66,7 +72,7 @@ dependencies:
66
72
  - - "~>"
67
73
  - !ruby/object:Gem::Version
68
74
  version: '13.0'
69
- description: Create simple and powerful use cases as objects.
75
+ description: Create simple and powerful use cases as Ruby objects.
70
76
  email:
71
77
  - rodrigo.serradura@gmail.com
72
78
  executables: []
@@ -81,23 +87,24 @@ files:
81
87
  - Gemfile
82
88
  - LICENSE.txt
83
89
  - README.md
90
+ - README.pt-BR.md
84
91
  - Rakefile
85
92
  - bin/console
86
93
  - bin/setup
87
94
  - lib/micro/case.rb
95
+ - lib/micro/case/config.rb
88
96
  - lib/micro/case/error.rb
89
- - lib/micro/case/flow.rb
90
- - lib/micro/case/flow/reducer.rb
91
97
  - lib/micro/case/result.rb
92
98
  - lib/micro/case/safe.rb
93
- - lib/micro/case/safe/flow.rb
94
99
  - lib/micro/case/strict.rb
95
100
  - lib/micro/case/utils.rb
96
101
  - lib/micro/case/version.rb
97
102
  - lib/micro/case/with_activemodel_validation.rb
103
+ - lib/micro/cases.rb
104
+ - lib/micro/cases/flow.rb
105
+ - lib/micro/cases/safe/flow.rb
98
106
  - lib/u-case.rb
99
107
  - lib/u-case/with_activemodel_validation.rb
100
- - lib/u-case/with_validation.rb
101
108
  - test.sh
102
109
  - u-case.gemspec
103
110
  homepage: https://github.com/serradura/u-case
@@ -115,12 +122,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
115
122
  version: 2.2.0
116
123
  required_rubygems_version: !ruby/object:Gem::Requirement
117
124
  requirements:
118
- - - ">="
125
+ - - ">"
119
126
  - !ruby/object:Gem::Version
120
- version: '0'
127
+ version: 1.3.1
121
128
  requirements: []
122
129
  rubygems_version: 3.0.6
123
130
  signing_key:
124
131
  specification_version: 4
125
- summary: Create simple and powerful use cases as objects.
132
+ summary: Create simple and powerful use cases as Ruby objects.
126
133
  test_files: []
@@ -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)
97
-
98
- next_use_case_result(use_case, result, input)
99
- end
100
- end
101
- end
102
- end
103
- end
104
- end