aux 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/MIT-LICENSE +7 -0
- data/aux.gemspec +1 -4
- data/lib/aux/carriers/failure.rb +47 -0
- data/lib/aux/carriers/success.rb +42 -0
- data/lib/aux/carriers.rb +59 -0
- data/lib/aux/pluggable/class_methods.rb +3 -3
- data/lib/aux/pluggable/connector.rb +3 -3
- data/lib/aux/validations/error.rb +6 -6
- data/lib/aux/validations/error_handler.rb +125 -0
- data/lib/aux/validations/errors.rb +28 -54
- data/lib/aux/validations.rb +3 -1
- data/lib/aux/version.rb +1 -1
- data/lib/aux.rb +1 -0
- metadata +11 -47
- data/lib/aux/validations/errors_tree_presenter.rb +0 -50
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a5a8f2a8523d27a026f50b5e10f3d87c0603a7e2a6710ec0f788b824075c98e0
|
4
|
+
data.tar.gz: 9e5873e8a90853626176568ddd63013a09e5dff9da442a54e6f5955344e2461f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a4a734ffb338fdb30efc987eaadc47378f733818681a126ceddd2d609116ced8cf23474607e8c5e633d65d7f71c232081c2da04b51ef2c840c242d6a1850b26e
|
7
|
+
data.tar.gz: 4a8982b1e6d9e1763676537c8ffb8c900f7209af29c096dab88acced564e5b1d25ef6f17644f2227e40fc872bea30a25f2db5a541a48c3e314db92444026bf68
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (c) 2022 Evgeny Boyko
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/aux.gemspec
CHANGED
@@ -4,7 +4,7 @@ Gem::Specification.new do |specification|
|
|
4
4
|
specification.name = 'aux'
|
5
5
|
specification.version = Aux::VERSION
|
6
6
|
specification.summary = 'Supplementary tools for more effective development'
|
7
|
-
specification.files = Dir['LICENSE', 'README.md', 'aux.gemspec', 'lib/**/*']
|
7
|
+
specification.files = Dir['MIT-LICENSE', 'README.md', 'aux.gemspec', 'lib/**/*']
|
8
8
|
|
9
9
|
specification.authors = ['Evgeny Boyko']
|
10
10
|
specification.email = ['eboyko@eboyko.ru']
|
@@ -13,9 +13,6 @@ Gem::Specification.new do |specification|
|
|
13
13
|
specification.add_dependency 'concurrent-ruby', '~> 1.2', '>= 1.2.3'
|
14
14
|
specification.add_dependency 'activemodel', '>= 6.1', '< 8'
|
15
15
|
|
16
|
-
specification.add_development_dependency 'zeitwerk', '~> 2.6', '>= 2.6.13'
|
17
|
-
specification.add_development_dependency 'rubocop', '~> 1.62', '>= 1.62.1'
|
18
|
-
|
19
16
|
specification.required_ruby_version = '>= 2.7.1'
|
20
17
|
specification.metadata['rubygems_mfa_required'] = 'true'
|
21
18
|
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Aux
|
4
|
+
module Carriers
|
5
|
+
# Describes a service failure
|
6
|
+
class Failure
|
7
|
+
# @!attribute [r] code
|
8
|
+
# @return [Symbol]
|
9
|
+
# @!attribute [r] details
|
10
|
+
# @return [Object, nil]
|
11
|
+
# @!attribute [r] payload
|
12
|
+
# @return [Object, nil]
|
13
|
+
attr_reader :code, :details, :payload
|
14
|
+
|
15
|
+
# @param code [Symbol]
|
16
|
+
# @param details [Object, nil]
|
17
|
+
# @param payload [Object, nil]
|
18
|
+
def initialize(code, details = nil, payload = nil)
|
19
|
+
@code = code
|
20
|
+
@details = details
|
21
|
+
@payload = payload
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [FalseClass]
|
25
|
+
def succeeded?
|
26
|
+
false
|
27
|
+
end
|
28
|
+
|
29
|
+
# @!method successful?
|
30
|
+
# @return [FalseClass]
|
31
|
+
alias successful? succeeded?
|
32
|
+
|
33
|
+
# @!method success?
|
34
|
+
# @return [FalseClass]
|
35
|
+
alias success? succeeded?
|
36
|
+
|
37
|
+
# @return [TrueClass]
|
38
|
+
def failed?
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
# @!method failure?
|
43
|
+
# @return [TrueClass]
|
44
|
+
alias failure? failed?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Aux
|
4
|
+
module Carriers
|
5
|
+
class Success
|
6
|
+
# @!attribute [r] code
|
7
|
+
# @return [Symbol]
|
8
|
+
# @!attribute [r] payload
|
9
|
+
# @return [Object, nil]
|
10
|
+
attr_reader :code, :payload
|
11
|
+
|
12
|
+
# @param code [Symbol]
|
13
|
+
# @param payload [Object, nil]
|
14
|
+
def initialize(code, payload = nil)
|
15
|
+
@code = code
|
16
|
+
@payload = payload
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [TrueClass]
|
20
|
+
def succeeded?
|
21
|
+
true
|
22
|
+
end
|
23
|
+
|
24
|
+
# @!method successful?
|
25
|
+
# @return [TrueClass]
|
26
|
+
alias successful? succeeded?
|
27
|
+
|
28
|
+
# @!method success?
|
29
|
+
# @return [TrueClass]
|
30
|
+
alias success? succeeded?
|
31
|
+
|
32
|
+
# @return [FalseClass]
|
33
|
+
def failed?
|
34
|
+
false
|
35
|
+
end
|
36
|
+
|
37
|
+
# @!method failure?
|
38
|
+
# @return [FalseClass]
|
39
|
+
alias failure? failed?
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/aux/carriers.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'aux/carriers/success'
|
4
|
+
require 'aux/carriers/failure'
|
5
|
+
|
6
|
+
module Aux
|
7
|
+
module Carriers
|
8
|
+
private
|
9
|
+
|
10
|
+
# @overload success
|
11
|
+
# @return [Success]
|
12
|
+
# @overload success(code)
|
13
|
+
# @param code [Symbol]
|
14
|
+
# @return [Success]
|
15
|
+
# @overload success(payload)
|
16
|
+
# @param payload [Object]
|
17
|
+
# @return [Success]
|
18
|
+
# @overload success(code, payload)
|
19
|
+
# @param code [Symbol]
|
20
|
+
# @param payload [Object]
|
21
|
+
# @return [Success]
|
22
|
+
def success(*arguments)
|
23
|
+
case arguments
|
24
|
+
in [Symbol] | [Symbol, Object]
|
25
|
+
Success.new(*arguments)
|
26
|
+
in [Object]
|
27
|
+
Success.new(:ok, *arguments)
|
28
|
+
else
|
29
|
+
Success.new(:ok)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# @overload failure
|
34
|
+
# @return [Failure]
|
35
|
+
# @overload failure(code)
|
36
|
+
# @param code [Symbol]
|
37
|
+
# @return [Failure]
|
38
|
+
# @overload failure(details)
|
39
|
+
# @param details [Object]
|
40
|
+
# @return [Failure]
|
41
|
+
# @overload failure(code, details)
|
42
|
+
# @param code [Symbol]
|
43
|
+
# @param details [Object]
|
44
|
+
# @return [Failure]
|
45
|
+
# @overload failure(code, details, payload)
|
46
|
+
# @param code [Symbol]
|
47
|
+
# @param details [Object]
|
48
|
+
# @param payload [Object]
|
49
|
+
# @return [Failure]
|
50
|
+
def failure(*arguments)
|
51
|
+
case arguments
|
52
|
+
in [Symbol] | [Symbol, Object] | [Symbol, Object, Object]
|
53
|
+
Failure.new(*arguments)
|
54
|
+
else
|
55
|
+
Failure.new(:internal_server_error, *arguments)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -20,7 +20,7 @@ module Aux
|
|
20
20
|
|
21
21
|
# Configure dependencies that come from the registry
|
22
22
|
pluggable.dependencies.each do |dependency|
|
23
|
-
instance.instance_variable_set("@#{dependency.pointer}", dependency.target)
|
23
|
+
instance.instance_variable_set(:"@#{dependency.pointer}", dependency.target)
|
24
24
|
|
25
25
|
# The next lines are required to make resolved dependencies available
|
26
26
|
# by its reader methods within customized initialization
|
@@ -28,7 +28,7 @@ module Aux
|
|
28
28
|
# TODO: Discuss whether this is appropriate behaviour
|
29
29
|
next if instance.respond_to?(dependency.pointer, true)
|
30
30
|
|
31
|
-
define_method(dependency.pointer) { instance_variable_get("@#{dependency.pointer}") }
|
31
|
+
define_method(dependency.pointer) { instance_variable_get(:"@#{dependency.pointer}") }
|
32
32
|
next unless dependency.private
|
33
33
|
|
34
34
|
private(dependency.pointer)
|
@@ -37,7 +37,7 @@ module Aux
|
|
37
37
|
# Configure dependencies that come from the customized initialization procedure
|
38
38
|
dependencies_overrides = keyword_arguments.slice(*dependencies_keys)
|
39
39
|
dependencies_overrides.each do |pointer, target|
|
40
|
-
instance.instance_variable_set("@#{pointer}", target)
|
40
|
+
instance.instance_variable_set(:"@#{pointer}", target)
|
41
41
|
end
|
42
42
|
|
43
43
|
# Run the origin's initialization procedure if any other arguments given
|
@@ -45,13 +45,13 @@ module Aux
|
|
45
45
|
|
46
46
|
if @initialization_required
|
47
47
|
@subject.class_eval do
|
48
|
-
define_method(dependency.pointer) { instance_variable_get("@#{dependency.pointer}") }
|
48
|
+
define_method(dependency.pointer) { instance_variable_get(:"@#{dependency.pointer}") }
|
49
49
|
private(dependency.pointer) if dependency.private
|
50
50
|
end
|
51
51
|
else
|
52
|
-
@subject.instance_variable_set("@#{dependency.pointer}", dependency.target)
|
52
|
+
@subject.instance_variable_set(:"@#{dependency.pointer}", dependency.target)
|
53
53
|
@subject.singleton_class.class_eval do
|
54
|
-
define_method(dependency.pointer) { instance_variable_get("@#{dependency.pointer}") }
|
54
|
+
define_method(dependency.pointer) { instance_variable_get(:"@#{dependency.pointer}") }
|
55
55
|
private(dependency.pointer) if dependency.private
|
56
56
|
end
|
57
57
|
end
|
@@ -6,22 +6,22 @@ module Aux
|
|
6
6
|
class Error
|
7
7
|
# @!attribute [r] attribute
|
8
8
|
# @return [Symbol]
|
9
|
-
# @!attribute [r] type
|
10
|
-
# @return [Symbol]
|
11
9
|
# @!attribute [r] scope
|
12
10
|
# @return [String]
|
11
|
+
# @!attribute [r] type
|
12
|
+
# @return [Symbol]
|
13
13
|
# @!attribute [r] details
|
14
14
|
# @return [Hash]
|
15
|
-
attr_reader :attribute, :
|
15
|
+
attr_reader :attribute, :scope, :type, :details
|
16
16
|
|
17
17
|
# @param attribute [Symbol]
|
18
|
-
# @param type [Symbol]
|
19
18
|
# @param scope [String]
|
19
|
+
# @param type [Symbol]
|
20
20
|
# @param details [Hash]
|
21
|
-
def initialize(attribute,
|
21
|
+
def initialize(attribute, scope, type, **details)
|
22
22
|
@attribute = attribute
|
23
|
-
@type = type
|
24
23
|
@scope = scope
|
24
|
+
@type = type
|
25
25
|
@details = details
|
26
26
|
end
|
27
27
|
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Aux
|
4
|
+
module Validations
|
5
|
+
# Describes methods that represent validation errors in simple structures pretty enough for the API response.
|
6
|
+
module ErrorHandler
|
7
|
+
private
|
8
|
+
|
9
|
+
DEFAULT_ERROR_SCOPE_PREFIX = 'errors'
|
10
|
+
GENERIC_ERROR_SCOPE = 'errors.generic'
|
11
|
+
|
12
|
+
# @overload format_errors(error_batch, scope)
|
13
|
+
# @param error_batch [Array]
|
14
|
+
# @param scope [Symbol, String, nil]
|
15
|
+
# @raise [ArgumentError]
|
16
|
+
# @return [Array<Hash>]
|
17
|
+
# @overload format_errors(error_collection, scope)
|
18
|
+
# @param error_collection [Errors]
|
19
|
+
# @param scope [Symbol, String, nil]
|
20
|
+
# @raise [ArgumentError]
|
21
|
+
# @return [Array<Hash>]
|
22
|
+
# @overload format_errors(error, scope)
|
23
|
+
# @param scope [Symbol, String, nil]
|
24
|
+
# @param error [Error]
|
25
|
+
# @raise [ArgumentError]
|
26
|
+
# @return [Hash]
|
27
|
+
def format_errors(payload, scope = nil)
|
28
|
+
case payload
|
29
|
+
when Array
|
30
|
+
format_error_batch(payload, scope)
|
31
|
+
when Errors
|
32
|
+
format_error_collection(payload, scope)
|
33
|
+
when Error
|
34
|
+
format_error(payload, scope)
|
35
|
+
else
|
36
|
+
raise ArgumentError
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# @param batch [Array<Error, Errors>]
|
41
|
+
# @param scope [Symbol, String, nil]
|
42
|
+
# @return [Array<Hash>]
|
43
|
+
def format_error_batch(batch, scope = nil)
|
44
|
+
batch.flat_map { |element| format_errors(element, scope) }
|
45
|
+
end
|
46
|
+
|
47
|
+
# @param collection [Errors]
|
48
|
+
# @param scope [Symbol, String, nil]
|
49
|
+
def format_error_collection(collection, scope = nil)
|
50
|
+
return format_primary_error_collection(collection, scope || collection.scope) unless collection.attribute
|
51
|
+
|
52
|
+
format_secondary_error_collection(collection, "#{scope}.#{collection.attribute}")
|
53
|
+
end
|
54
|
+
|
55
|
+
# @param collection [Errors]
|
56
|
+
# @param scope [Symbol, String, nil]
|
57
|
+
# @return [Array<Hash>]
|
58
|
+
def format_primary_error_collection(collection, scope = nil)
|
59
|
+
collection.group_by_attribute.map do |attribute, entities|
|
60
|
+
{
|
61
|
+
kind: entities.all?(Error) ? 'collection' : 'batch',
|
62
|
+
attribute: attribute,
|
63
|
+
errors: format_errors(entities, scope)
|
64
|
+
}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# @param collection [Errors]
|
69
|
+
# @param scope [Symbol, String, nil]
|
70
|
+
# @return [Array<Hash>]
|
71
|
+
def format_secondary_error_collection(collection, scope = nil)
|
72
|
+
collection.group_by_attribute.flat_map do |_attribute, items|
|
73
|
+
format_errors(items.one? ? items.first : items, scope)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# @param error [Error]
|
78
|
+
# @param scope [Symbol, String, nil]
|
79
|
+
# @return [Hash]
|
80
|
+
def format_error(error, scope = nil)
|
81
|
+
{
|
82
|
+
type: error.type,
|
83
|
+
details: error.details,
|
84
|
+
message: format_message(error, scope)
|
85
|
+
}
|
86
|
+
end
|
87
|
+
|
88
|
+
# @param error [Error]
|
89
|
+
# @param scope [Symbol, String, nil]
|
90
|
+
# @return [String]
|
91
|
+
def format_message(error, scope = nil)
|
92
|
+
scope ? format_secondary_message(error, scope) : format_primary_message(error)
|
93
|
+
end
|
94
|
+
|
95
|
+
# @param error [Error]
|
96
|
+
# @return [String]
|
97
|
+
def format_primary_message(error)
|
98
|
+
I18n.translate(
|
99
|
+
error.type,
|
100
|
+
scope: "#{self.class::DEFAULT_ERROR_SCOPE_PREFIX}.#{error.scope}.#{error.attribute}",
|
101
|
+
default: proc { format_fallback_message(error) },
|
102
|
+
**error.details
|
103
|
+
)
|
104
|
+
end
|
105
|
+
|
106
|
+
# @param error [Error]
|
107
|
+
# @param scope [Symbol, String, nil]
|
108
|
+
# @return [String]
|
109
|
+
def format_secondary_message(error, scope)
|
110
|
+
I18n.translate(
|
111
|
+
error.type,
|
112
|
+
scope: "#{self.class::DEFAULT_ERROR_SCOPE_PREFIX}.#{scope}.#{error.attribute}",
|
113
|
+
default: proc { format_primary_message(error) },
|
114
|
+
**error.details
|
115
|
+
)
|
116
|
+
end
|
117
|
+
|
118
|
+
# @param error [Error]
|
119
|
+
# @return [String]
|
120
|
+
def format_fallback_message(error)
|
121
|
+
I18n.translate(error.type, scope: self.class::GENERIC_ERROR_SCOPE, default: error.type)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -1,11 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'aux/validations/error'
|
4
|
-
require 'aux/validations/errors_tree_presenter'
|
5
|
-
|
6
3
|
module Aux
|
7
4
|
module Validations
|
8
|
-
# Describes a
|
5
|
+
# Describes a collection of errors that can be initialized with an attribute name or an object to be validated
|
9
6
|
class Errors
|
10
7
|
# @!attribute [r] scope
|
11
8
|
# @return [String, nil]
|
@@ -14,16 +11,13 @@ module Aux
|
|
14
11
|
attr_reader :scope, :attribute
|
15
12
|
|
16
13
|
# @overload initialize(subject)
|
17
|
-
# @param
|
18
|
-
# @return [self]
|
14
|
+
# @param subject [Object]
|
19
15
|
# @overload initialize(attribute, errors)
|
20
|
-
# Use this approach to handle nested errors
|
21
16
|
# @param attribute [Symbol]
|
22
|
-
# @param errors [
|
23
|
-
|
24
|
-
|
25
|
-
@
|
26
|
-
@attribute = base.is_a?(Symbol) ? base : nil
|
17
|
+
# @param errors [Errors]
|
18
|
+
def initialize(subject, errors = [])
|
19
|
+
@scope = subject.is_a?(Symbol) ? nil : subject.class.name.underscore.tr('/', '.')
|
20
|
+
@attribute = subject.is_a?(Symbol) ? subject : nil
|
27
21
|
@errors = errors
|
28
22
|
end
|
29
23
|
|
@@ -34,35 +28,25 @@ module Aux
|
|
34
28
|
# @raise [StandardError]
|
35
29
|
# @overload add(attribute, errors)
|
36
30
|
# @param attribute [Symbol]
|
37
|
-
# @param errors [Array<
|
31
|
+
# @param errors [Array<Errors, Error>]
|
38
32
|
# @raise [StandardError]
|
39
33
|
# @overload add(attribute, errors)
|
40
34
|
# @param attribute [Symbol]
|
41
|
-
# @param errors [
|
35
|
+
# @param errors [Errors]
|
42
36
|
# @raise [StandardError]
|
43
|
-
def add(attribute,
|
44
|
-
case
|
37
|
+
def add(attribute, subject, **details)
|
38
|
+
case subject
|
45
39
|
when Symbol
|
46
|
-
add_error(attribute,
|
40
|
+
add_error(attribute, subject, **details)
|
47
41
|
when Array
|
48
|
-
add_nested_error(attribute,
|
49
|
-
when
|
50
|
-
add_nested_error(attribute, [
|
42
|
+
add_nested_error(attribute, subject)
|
43
|
+
when Errors
|
44
|
+
add_nested_error(attribute, [subject])
|
51
45
|
else
|
52
|
-
raise
|
46
|
+
raise(ArgumentError, "Unsupported argument given (#{subject.class})")
|
53
47
|
end
|
54
48
|
end
|
55
49
|
|
56
|
-
# @return [Hash]
|
57
|
-
def tree
|
58
|
-
tree_presenter.render(self)
|
59
|
-
end
|
60
|
-
|
61
|
-
# @return [Hash]
|
62
|
-
def group_by_attribute
|
63
|
-
errors.group_by(&:attribute)
|
64
|
-
end
|
65
|
-
|
66
50
|
def clear
|
67
51
|
self.errors = []
|
68
52
|
end
|
@@ -72,25 +56,20 @@ module Aux
|
|
72
56
|
errors.empty?
|
73
57
|
end
|
74
58
|
|
59
|
+
# @param block [Proc]
|
75
60
|
def map(&block)
|
76
61
|
errors.map(&block)
|
77
62
|
end
|
78
63
|
|
79
|
-
# @return [Array
|
80
|
-
def
|
81
|
-
errors.
|
82
|
-
if error.is_a?(Array)
|
83
|
-
error.map { |e| e.respond_to?(:all) ? e.all : e }
|
84
|
-
else
|
85
|
-
error.respond_to?(:all) ? error.all : error
|
86
|
-
end
|
87
|
-
end.flatten
|
64
|
+
# @return [Hash<Symbol, Array>]
|
65
|
+
def group_by_attribute
|
66
|
+
errors.group_by(&:attribute)
|
88
67
|
end
|
89
68
|
|
90
69
|
private
|
91
70
|
|
92
71
|
# @!attribute [rw] errors
|
93
|
-
# @return [Array<
|
72
|
+
# @return [Array<Error, Errors>]
|
94
73
|
attr_accessor :errors
|
95
74
|
|
96
75
|
# @param attribute [Symbol]
|
@@ -101,7 +80,7 @@ module Aux
|
|
101
80
|
end
|
102
81
|
|
103
82
|
# @param attribute [Symbol]
|
104
|
-
# @param nested_errors [
|
83
|
+
# @param nested_errors [Errors]
|
105
84
|
def add_nested_error(attribute, nested_errors)
|
106
85
|
errors.push(build_nested_error(attribute, nested_errors))
|
107
86
|
end
|
@@ -109,26 +88,21 @@ module Aux
|
|
109
88
|
# @param attribute [Symbol]
|
110
89
|
# @param type [Symbol]
|
111
90
|
# @param details [Hash]
|
112
|
-
# @return [
|
91
|
+
# @return [Error]
|
113
92
|
def build_error(attribute, type, **details)
|
114
|
-
|
93
|
+
factory.new(attribute, scope, type, **details)
|
115
94
|
end
|
116
95
|
|
117
96
|
# @param attribute [Symbol] 3
|
118
|
-
# @param errors [
|
119
|
-
# @return [
|
97
|
+
# @param errors [Errors]
|
98
|
+
# @return [Errors]
|
120
99
|
def build_nested_error(attribute, errors)
|
121
100
|
self.class.new(attribute, errors)
|
122
101
|
end
|
123
102
|
|
124
|
-
# @return [Class<
|
125
|
-
def
|
126
|
-
|
127
|
-
end
|
128
|
-
|
129
|
-
# @return [Class<Aux::Validations::Error>]
|
130
|
-
def errors_factory
|
131
|
-
Aux::Validations::Error
|
103
|
+
# @return [Class<Error>]
|
104
|
+
def factory
|
105
|
+
Error
|
132
106
|
end
|
133
107
|
end
|
134
108
|
end
|
data/lib/aux/validations.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'active_model'
|
3
4
|
require 'active_support'
|
4
|
-
require '
|
5
|
+
require 'aux/validations/error'
|
5
6
|
require 'aux/validations/errors'
|
7
|
+
require 'aux/validations/error_handler'
|
6
8
|
|
7
9
|
module Aux
|
8
10
|
# Describes enhancement of {::ActiveModel::Validations}
|
data/lib/aux/version.rb
CHANGED
data/lib/aux.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aux
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evgeny Boyko
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-08-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -50,56 +50,20 @@ dependencies:
|
|
50
50
|
- - "<"
|
51
51
|
- !ruby/object:Gem::Version
|
52
52
|
version: '8'
|
53
|
-
|
54
|
-
name: zeitwerk
|
55
|
-
requirement: !ruby/object:Gem::Requirement
|
56
|
-
requirements:
|
57
|
-
- - "~>"
|
58
|
-
- !ruby/object:Gem::Version
|
59
|
-
version: '2.6'
|
60
|
-
- - ">="
|
61
|
-
- !ruby/object:Gem::Version
|
62
|
-
version: 2.6.13
|
63
|
-
type: :development
|
64
|
-
prerelease: false
|
65
|
-
version_requirements: !ruby/object:Gem::Requirement
|
66
|
-
requirements:
|
67
|
-
- - "~>"
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version: '2.6'
|
70
|
-
- - ">="
|
71
|
-
- !ruby/object:Gem::Version
|
72
|
-
version: 2.6.13
|
73
|
-
- !ruby/object:Gem::Dependency
|
74
|
-
name: rubocop
|
75
|
-
requirement: !ruby/object:Gem::Requirement
|
76
|
-
requirements:
|
77
|
-
- - "~>"
|
78
|
-
- !ruby/object:Gem::Version
|
79
|
-
version: '1.62'
|
80
|
-
- - ">="
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: 1.62.1
|
83
|
-
type: :development
|
84
|
-
prerelease: false
|
85
|
-
version_requirements: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - "~>"
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '1.62'
|
90
|
-
- - ">="
|
91
|
-
- !ruby/object:Gem::Version
|
92
|
-
version: 1.62.1
|
93
|
-
description:
|
53
|
+
description:
|
94
54
|
email:
|
95
55
|
- eboyko@eboyko.ru
|
96
56
|
executables: []
|
97
57
|
extensions: []
|
98
58
|
extra_rdoc_files: []
|
99
59
|
files:
|
60
|
+
- MIT-LICENSE
|
100
61
|
- README.md
|
101
62
|
- aux.gemspec
|
102
63
|
- lib/aux.rb
|
64
|
+
- lib/aux/carriers.rb
|
65
|
+
- lib/aux/carriers/failure.rb
|
66
|
+
- lib/aux/carriers/success.rb
|
103
67
|
- lib/aux/pluggable.rb
|
104
68
|
- lib/aux/pluggable/class_methods.rb
|
105
69
|
- lib/aux/pluggable/connector.rb
|
@@ -109,15 +73,15 @@ files:
|
|
109
73
|
- lib/aux/registry/entry.rb
|
110
74
|
- lib/aux/validations.rb
|
111
75
|
- lib/aux/validations/error.rb
|
76
|
+
- lib/aux/validations/error_handler.rb
|
112
77
|
- lib/aux/validations/errors.rb
|
113
|
-
- lib/aux/validations/errors_tree_presenter.rb
|
114
78
|
- lib/aux/version.rb
|
115
79
|
homepage: https://github.com/eboyko/aux
|
116
80
|
licenses:
|
117
81
|
- MIT
|
118
82
|
metadata:
|
119
83
|
rubygems_mfa_required: 'true'
|
120
|
-
post_install_message:
|
84
|
+
post_install_message:
|
121
85
|
rdoc_options: []
|
122
86
|
require_paths:
|
123
87
|
- lib
|
@@ -133,7 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
133
97
|
version: '0'
|
134
98
|
requirements: []
|
135
99
|
rubygems_version: 3.1.2
|
136
|
-
signing_key:
|
100
|
+
signing_key:
|
137
101
|
specification_version: 4
|
138
102
|
summary: Supplementary tools for more effective development
|
139
103
|
test_files: []
|
@@ -1,50 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Aux
|
4
|
-
module Validations
|
5
|
-
# Describes tree structure presentation scenario of errors
|
6
|
-
class ErrorsTreePresenter
|
7
|
-
class << self
|
8
|
-
# @return [Array, Hash, Aux::Validations::Error]
|
9
|
-
def render(payload)
|
10
|
-
case payload
|
11
|
-
when Array
|
12
|
-
process_array(payload)
|
13
|
-
when Aux::Validations::Errors
|
14
|
-
render_collection(payload)
|
15
|
-
when Aux::Validations::Error
|
16
|
-
payload
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
# @param errors [Array]
|
23
|
-
# @return [Array]
|
24
|
-
def process_array(errors)
|
25
|
-
errors.map { |item| render(item) }.flatten
|
26
|
-
end
|
27
|
-
|
28
|
-
# @param errors [Aux::Validations::Errors]
|
29
|
-
# @return [Array, Hash]
|
30
|
-
def render_collection(errors)
|
31
|
-
errors.attribute ? process_attribute_errors(errors) : process_errors(errors)
|
32
|
-
end
|
33
|
-
|
34
|
-
# @param errors [Aux::Validations::Errors]
|
35
|
-
# @return [Hash]
|
36
|
-
def process_errors(errors)
|
37
|
-
errors.group_by_attribute.transform_values do |items|
|
38
|
-
render(items.one? ? items.first : items)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
# @param errors [Aux::Validations::Errors]
|
43
|
-
# @return [Array]
|
44
|
-
def process_attribute_errors(errors)
|
45
|
-
errors.group_by_attribute.map { |_attribute, items| render(items) }.flatten
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|