u-case 3.0.0.rc9 → 4.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
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
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Micro
4
+ class Case
5
+ class Result
6
+ class Wrapper
7
+ def initialize(result)
8
+ @__is_unknown = true
9
+
10
+ @result = result
11
+ end
12
+
13
+ def failure(type = nil)
14
+ return if @result.success?
15
+
16
+ if result_type?(type)
17
+ @__is_unknown = false
18
+
19
+ yield(@result)
20
+ end
21
+ end
22
+
23
+ def success(type = nil)
24
+ return if @result.failure?
25
+
26
+ if result_type?(type)
27
+ @__is_unknown = false
28
+
29
+ yield(@result)
30
+ end
31
+ end
32
+
33
+ def unknown
34
+ return yield(@result) if @__is_unknown
35
+ end
36
+
37
+ private
38
+
39
+ def result_type?(type)
40
+ type.nil? || @result.type == type
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -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_the_use_case_or_its_flow
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
@@ -3,24 +3,34 @@
3
3
  module Micro
4
4
  class Case
5
5
  module Utils
6
- def self.symbolize_hash_keys(hash)
7
- if Kind::Of::Hash(hash).respond_to?(:transform_keys)
8
- hash.transform_keys { |key| key.to_sym rescue key }
9
- else
6
+
7
+ module Hashes
8
+ def self.respond_to?(hash, method)
9
+ Kind.of(Hash, hash).respond_to?(method)
10
+ end
11
+
12
+ def self.symbolize_keys(hash)
13
+ return hash.transform_keys { |key| key.to_sym rescue key } if respond_to?(hash, :transform_keys)
14
+
10
15
  hash.each_with_object({}) do |(k, v), memo|
11
16
  key = k.to_sym rescue k
12
-
13
17
  memo[key] = v
14
18
  end
15
19
  end
16
- end
17
- def self.slice_hash(hash, keys)
18
- if Kind::Of::Hash(hash).respond_to?(:slice)
19
- hash.slice(*keys)
20
- else
20
+
21
+ def self.stringify_keys(hash)
22
+ return hash.transform_keys(&:to_s) if respond_to?(hash, :transform_keys)
23
+
24
+ hash.each_with_object({}) { |(k, v), memo| memo[k.to_s] = v }
25
+ end
26
+
27
+ def self.slice(hash, keys)
28
+ return hash.slice(*keys) if respond_to?(hash, :slice)
29
+
21
30
  hash.select { |key, _value| keys.include?(key) }
22
31
  end
23
32
  end
33
+
24
34
  end
25
35
  end
26
36
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Micro
4
4
  class Case
5
- VERSION = '3.0.0.rc9'.freeze
5
+ VERSION = '4.1.1'.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
@@ -1,7 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'micro/cases/utils'
4
+ require 'micro/cases/error'
3
5
  require 'micro/cases/flow'
4
6
  require 'micro/cases/safe/flow'
7
+ require 'micro/cases/map'
5
8
 
6
9
  module Micro
7
10
  module Cases
@@ -12,5 +15,9 @@ module Micro
12
15
  def self.safe_flow(args)
13
16
  Safe::Flow.build(args)
14
17
  end
18
+
19
+ def self.map(args)
20
+ Map.build(args)
21
+ end
15
22
  end
16
23
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Micro
4
+ module Cases
5
+
6
+ module Error
7
+ class InvalidUseCases < ArgumentError
8
+ def initialize; super('argument must be a collection of `Micro::Case` classes'.freeze); end
9
+ end
10
+ end
11
+
12
+ end
13
+ end
@@ -3,42 +3,43 @@
3
3
  module Micro
4
4
  module Cases
5
5
  class Flow
6
- class InvalidUseCases < ArgumentError
7
- def initialize; super('argument must be a collection of `Micro::Case` classes'.freeze); end
8
- end
6
+ IsAUseCaseWithDefaults = -> arg { arg.is_a?(Array) && Micro.case?(arg[0]) && arg[1].is_a?(Hash) }
7
+ IsAValidUseCase = -> use_case { Micro.case?(use_case) || IsAUseCaseWithDefaults[use_case] }
9
8
 
10
9
  attr_reader :use_cases
11
10
 
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
11
  def self.build(args)
19
- use_cases = Array(args).flat_map { |arg| map_use_cases(arg) }
12
+ use_cases = Utils.map_use_cases(args)
20
13
 
21
- raise InvalidUseCases if use_cases.any? { |klass| !(klass < ::Micro::Case) }
14
+ raise Error::InvalidUseCases if use_cases.none?(&IsAValidUseCase)
22
15
 
23
16
  new(use_cases)
24
17
  end
25
18
 
26
19
  def initialize(use_cases)
27
- @use_cases = use_cases
28
- @first_use_case = use_cases[0]
29
- @next_use_cases = use_cases[1..-1]
20
+ @use_cases = use_cases.dup.freeze
21
+ @next_ones = use_cases.dup
22
+ @first = @next_ones.shift
23
+ end
24
+
25
+ def inspect
26
+ '<(%s) use_cases=%s>' % [self.class, @use_cases]
30
27
  end
31
28
 
32
29
  def call!(input:, result:)
33
- first_result = __next_use_case_result(@first_use_case, result, input)
30
+ first_result = __call_use_case(@first, result, input)
34
31
 
35
- return first_result if @next_use_cases.empty?
32
+ return first_result if @next_ones.empty?
36
33
 
37
- __next_use_cases_result(first_result)
34
+ __call_next_use_cases(first_result)
38
35
  end
39
36
 
40
37
  def call(input = Kind::Empty::HASH)
41
- call!(input: input, result: Case::Result.new)
38
+ result = call!(input: input, result: Case::Result.new)
39
+
40
+ return result unless block_given?
41
+
42
+ yield ::Micro::Case::Result::Wrapper.new(result)
42
43
  end
43
44
 
44
45
  alias __call__ call
@@ -51,30 +52,42 @@ module Micro
51
52
  can_yield_self = respond_to?(:yield_self)
52
53
 
53
54
  if block
54
- raise Error::InvalidInvocationOfTheThenMethod if use_case
55
+ raise_invalid_invocation_of_the_then_method if use_case
55
56
  raise NotImplementedError if !can_yield_self
56
57
 
57
58
  yield_self(&block)
58
59
  else
59
60
  return yield_self if !use_case && can_yield_self
60
61
 
62
+ raise_invalid_invocation_of_the_then_method unless ::Micro.case_or_flow?(use_case)
63
+
61
64
  self.call.then(use_case)
62
65
  end
63
66
  end
64
67
 
65
68
  private
66
69
 
67
- def __next_use_case_result(use_case, result, input)
68
- use_case.__new__(result, input).__call__
70
+ def raise_invalid_invocation_of_the_then_method
71
+ raise Case::Error::InvalidInvocationOfTheThenMethod.new("#{self.class.name}#")
72
+ end
73
+
74
+ def __call_use_case(use_case, result, input)
75
+ __build_use_case(use_case, result, input).__call__
69
76
  end
70
77
 
71
- def __next_use_cases_result(first_result)
72
- @next_use_cases.reduce(first_result) do |result, use_case|
78
+ def __call_next_use_cases(first_result)
79
+ @next_ones.reduce(first_result) do |result, use_case|
73
80
  break result if result.failure?
74
81
 
75
- __next_use_case_result(use_case, result, result.data)
82
+ __call_use_case(use_case, result, result.data)
76
83
  end
77
84
  end
85
+
86
+ def __build_use_case(use_case, result, input)
87
+ return use_case.__new__(result, input) unless use_case.is_a?(Array)
88
+
89
+ use_case[0].__new__(result, input.merge(use_case[1]))
90
+ end
78
91
  end
79
92
  end
80
93
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Micro
4
+ module Cases
5
+ class Map
6
+ IsAUseCaseOrFlowWithDefaults = -> arg { arg.is_a?(Array) && Micro.case_or_flow?(arg[0]) && arg[1].is_a?(Hash) }
7
+ IsAUseCaseOrFlow = -> arg { Micro.case_or_flow?(arg) || IsAUseCaseOrFlowWithDefaults[arg] }
8
+ HasValidArgs = -> (args) { Kind.of(Array, args).all?(&IsAUseCaseOrFlow) }
9
+
10
+ attr_reader :use_cases
11
+
12
+ def self.build(args)
13
+ raise Error::InvalidUseCases unless HasValidArgs[args]
14
+
15
+ new(args)
16
+ end
17
+
18
+ def initialize(use_cases)
19
+ @use_cases = use_cases
20
+ end
21
+
22
+ GetUseCaseResult = -> (hash) do
23
+ -> (use_case) do
24
+ return use_case.call(hash) unless use_case.is_a?(Array)
25
+
26
+ use_case[0].call(hash.merge(use_case[1]))
27
+ end
28
+ end
29
+
30
+ def call(arg = {})
31
+ hash = Kind.of(Hash, arg)
32
+
33
+ use_cases.map(&GetUseCaseResult[hash])
34
+ end
35
+
36
+ private_constant :HasValidArgs, :IsAUseCaseOrFlow, :IsAUseCaseOrFlowWithDefaults, :GetUseCaseResult
37
+ end
38
+ end
39
+ end
@@ -4,8 +4,8 @@ module Micro
4
4
  module Cases
5
5
  module Safe
6
6
  class Flow < Cases::Flow
7
- private def __next_use_case_result(use_case, result, input)
8
- instance = use_case.__new__(result, input)
7
+ private def __call_use_case(use_case, result, input)
8
+ instance = __build_use_case(use_case, result, input)
9
9
  instance.__call__
10
10
  rescue => exception
11
11
  raise exception if Case::Error.by_wrong_usage?(exception)
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Micro
4
+ module Cases
5
+
6
+ module Utils
7
+ def self.map_use_cases(args)
8
+ collection = args.is_a?(Array) && args.size == 1 ? args[0] : args
9
+
10
+ Array(collection).each_with_object([]) do |arg, memo|
11
+ if arg.is_a?(Flow)
12
+ arg.use_cases.each { |use_case| memo << use_case }
13
+ else
14
+ memo << arg
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -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 Ruby objects.}
13
- spec.description = %q{Create simple and powerful use cases as Ruby objects.}
12
+ spec.summary = %q{Represent use cases in a simple and powerful way while writing modular, expressive and sequentially logical code.}
13
+ spec.description = %q{Represent use cases in a simple and powerful way while writing modular, expressive and sequentially logical code.}
14
14
  spec.homepage = 'https://github.com/serradura/u-case'
15
15
  spec.license = 'MIT'
16
16
 
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
26
26
  spec.required_ruby_version = '>= 2.2.0'
27
27
 
28
28
  spec.add_runtime_dependency 'kind', '>= 3.0', '< 5.0'
29
- spec.add_runtime_dependency 'u-attributes', '~> 1.1'
29
+ spec.add_runtime_dependency 'u-attributes', '~> 2.0'
30
30
 
31
31
  spec.add_development_dependency 'bundler'
32
32
  spec.add_development_dependency 'rake', '~> 13.0'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: u-case
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0.rc9
4
+ version: 4.1.1
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-08-14 00:00:00.000000000 Z
11
+ date: 2020-10-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: kind
@@ -36,14 +36,14 @@ dependencies:
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '1.1'
39
+ version: '2.0'
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '1.1'
46
+ version: '2.0'
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: bundler
49
49
  requirement: !ruby/object:Gem::Requirement
@@ -72,7 +72,8 @@ dependencies:
72
72
  - - "~>"
73
73
  - !ruby/object:Gem::Version
74
74
  version: '13.0'
75
- description: Create simple and powerful use cases as Ruby objects.
75
+ description: Represent use cases in a simple and powerful way while writing modular,
76
+ expressive and sequentially logical code.
76
77
  email:
77
78
  - rodrigo.serradura@gmail.com
78
79
  executables: []
@@ -95,14 +96,19 @@ files:
95
96
  - lib/micro/case/config.rb
96
97
  - lib/micro/case/error.rb
97
98
  - lib/micro/case/result.rb
99
+ - lib/micro/case/result/transitions.rb
100
+ - lib/micro/case/result/wrapper.rb
98
101
  - lib/micro/case/safe.rb
99
102
  - lib/micro/case/strict.rb
100
103
  - lib/micro/case/utils.rb
101
104
  - lib/micro/case/version.rb
102
105
  - lib/micro/case/with_activemodel_validation.rb
103
106
  - lib/micro/cases.rb
107
+ - lib/micro/cases/error.rb
104
108
  - lib/micro/cases/flow.rb
109
+ - lib/micro/cases/map.rb
105
110
  - lib/micro/cases/safe/flow.rb
111
+ - lib/micro/cases/utils.rb
106
112
  - lib/u-case.rb
107
113
  - lib/u-case/with_activemodel_validation.rb
108
114
  - test.sh
@@ -122,12 +128,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
122
128
  version: 2.2.0
123
129
  required_rubygems_version: !ruby/object:Gem::Requirement
124
130
  requirements:
125
- - - ">"
131
+ - - ">="
126
132
  - !ruby/object:Gem::Version
127
- version: 1.3.1
133
+ version: '0'
128
134
  requirements: []
129
135
  rubygems_version: 3.0.6
130
136
  signing_key:
131
137
  specification_version: 4
132
- summary: Create simple and powerful use cases as Ruby objects.
138
+ summary: Represent use cases in a simple and powerful way while writing modular, expressive
139
+ and sequentially logical code.
133
140
  test_files: []