u-case 2.6.0 → 3.0.0.rc5

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 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