servactory 3.0.0.rc3 → 3.0.0.rc4
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.
- checksums.yaml +4 -4
- data/lib/servactory/context/warehouse/base.rb +20 -4
- data/lib/servactory/context/warehouse/crate.rb +39 -0
- data/lib/servactory/context/warehouse/inputs.rb +41 -10
- data/lib/servactory/context/warehouse/internals.rb +7 -2
- data/lib/servactory/context/warehouse/outputs.rb +7 -0
- data/lib/servactory/context/warehouse/setup.rb +53 -30
- data/lib/servactory/context/workspace/inputs.rb +6 -8
- data/lib/servactory/context/workspace/internals.rb +5 -7
- data/lib/servactory/context/workspace/outputs.rb +5 -7
- data/lib/servactory/inputs/input.rb +28 -18
- data/lib/servactory/inputs/tools/validation.rb +9 -9
- data/lib/servactory/inputs/validations/required.rb +51 -27
- data/lib/servactory/internals/internal.rb +20 -16
- data/lib/servactory/maintenance/attributes/tools/validation.rb +9 -10
- data/lib/servactory/maintenance/attributes/validations/concerns/error_builder.rb +52 -0
- data/lib/servactory/maintenance/attributes/validations/must.rb +164 -57
- data/lib/servactory/maintenance/attributes/validations/type.rb +77 -27
- data/lib/servactory/maintenance/validations/types.rb +18 -33
- data/lib/servactory/outputs/output.rb +18 -13
- data/lib/servactory/result.rb +266 -43
- data/lib/servactory/version.rb +1 -1
- metadata +3 -6
- data/lib/servactory/inputs/validations/base.rb +0 -21
- data/lib/servactory/inputs/validations/errors.rb +0 -17
- data/lib/servactory/maintenance/attributes/tools/check_errors.rb +0 -23
- data/lib/servactory/maintenance/attributes/validations/base.rb +0 -23
- data/lib/servactory/maintenance/attributes/validations/errors.rb +0 -19
|
@@ -13,6 +13,7 @@ module Servactory
|
|
|
13
13
|
@context = context
|
|
14
14
|
@attribute = attribute
|
|
15
15
|
@value = value
|
|
16
|
+
@first_error = nil
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
def validate!
|
|
@@ -26,22 +27,24 @@ module Servactory
|
|
|
26
27
|
def process
|
|
27
28
|
@attribute.options_for_checks.each do |check_key, check_options|
|
|
28
29
|
process_option(check_key, check_options)
|
|
30
|
+
break if @first_error.present?
|
|
29
31
|
end
|
|
30
32
|
end
|
|
31
33
|
|
|
32
|
-
def process_option(check_key, check_options)
|
|
34
|
+
def process_option(check_key, check_options) # rubocop:disable Metrics/MethodLength
|
|
33
35
|
return if validation_classes.empty?
|
|
34
36
|
|
|
35
37
|
validation_classes.each do |validation_class|
|
|
36
|
-
|
|
38
|
+
error_message = process_validation_class(
|
|
37
39
|
validation_class:,
|
|
38
40
|
check_key:,
|
|
39
41
|
check_options:
|
|
40
42
|
)
|
|
41
43
|
|
|
42
|
-
next if
|
|
44
|
+
next if error_message.blank?
|
|
43
45
|
|
|
44
|
-
|
|
46
|
+
@first_error = error_message
|
|
47
|
+
break
|
|
45
48
|
end
|
|
46
49
|
end
|
|
47
50
|
|
|
@@ -67,16 +70,12 @@ module Servactory
|
|
|
67
70
|
|
|
68
71
|
########################################################################
|
|
69
72
|
|
|
70
|
-
def errors
|
|
71
|
-
@errors ||= Servactory::Maintenance::Attributes::Tools::CheckErrors.new
|
|
72
|
-
end
|
|
73
|
-
|
|
74
73
|
def raise_errors
|
|
75
|
-
return if
|
|
74
|
+
return if @first_error.nil?
|
|
76
75
|
|
|
77
76
|
raise @context.config
|
|
78
77
|
.public_send(:"#{@attribute.system_name}_exception_class")
|
|
79
|
-
.new(context: @context, message:
|
|
78
|
+
.new(context: @context, message: @first_error)
|
|
80
79
|
end
|
|
81
80
|
end
|
|
82
81
|
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Servactory
|
|
4
|
+
module Maintenance
|
|
5
|
+
module Attributes
|
|
6
|
+
module Validations
|
|
7
|
+
module Concerns
|
|
8
|
+
# Concern providing error message processing for validators.
|
|
9
|
+
#
|
|
10
|
+
# ## Purpose
|
|
11
|
+
#
|
|
12
|
+
# ErrorBuilder provides shared logic for processing error messages that
|
|
13
|
+
# can be either static strings or dynamic Procs. This allows validators
|
|
14
|
+
# to support both simple error messages and context-aware messages.
|
|
15
|
+
#
|
|
16
|
+
# ## Usage
|
|
17
|
+
#
|
|
18
|
+
# Extend in validator classes:
|
|
19
|
+
#
|
|
20
|
+
# ```ruby
|
|
21
|
+
# class MyValidator
|
|
22
|
+
# extend Concerns::ErrorBuilder
|
|
23
|
+
#
|
|
24
|
+
# def self.build_error(...)
|
|
25
|
+
# process_message(message, **context)
|
|
26
|
+
# end
|
|
27
|
+
# end
|
|
28
|
+
# ```
|
|
29
|
+
#
|
|
30
|
+
# ## Methods Provided
|
|
31
|
+
#
|
|
32
|
+
# - `process_message` - converts String or Proc message to String
|
|
33
|
+
module ErrorBuilder
|
|
34
|
+
# Processes a message that may be a String or Proc.
|
|
35
|
+
#
|
|
36
|
+
# If message is a Proc, calls it with the provided attributes.
|
|
37
|
+
# If message is a String, returns it unchanged.
|
|
38
|
+
#
|
|
39
|
+
# @param message [String, Proc] The message to process
|
|
40
|
+
# @param attributes [Hash] Attributes to pass to Proc if message is callable
|
|
41
|
+
# @return [String] The processed message string
|
|
42
|
+
def process_message(message, **attributes)
|
|
43
|
+
return message unless message.is_a?(Proc)
|
|
44
|
+
|
|
45
|
+
message.call(**attributes)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -4,87 +4,194 @@ module Servactory
|
|
|
4
4
|
module Maintenance
|
|
5
5
|
module Attributes
|
|
6
6
|
module Validations
|
|
7
|
-
|
|
7
|
+
# Validates custom conditions defined with `must` option.
|
|
8
|
+
#
|
|
9
|
+
# ## Purpose
|
|
10
|
+
#
|
|
11
|
+
# Must validator executes user-defined validation lambdas against attribute
|
|
12
|
+
# values. It supports multiple named conditions per attribute and provides
|
|
13
|
+
# rich error context including custom messages, reason codes, and metadata.
|
|
14
|
+
#
|
|
15
|
+
# ## Usage
|
|
16
|
+
#
|
|
17
|
+
# Define must conditions on any attribute (input, internal, output):
|
|
18
|
+
#
|
|
19
|
+
# ```ruby
|
|
20
|
+
# class MyService < ApplicationService::Base
|
|
21
|
+
# input :age,
|
|
22
|
+
# type: Integer,
|
|
23
|
+
# must: {
|
|
24
|
+
# be_adult: {
|
|
25
|
+
# is: ->(value:) { value >= 18 },
|
|
26
|
+
# message: "Must be 18 or older"
|
|
27
|
+
# }
|
|
28
|
+
# }
|
|
29
|
+
#
|
|
30
|
+
# internal :discount,
|
|
31
|
+
# type: Float,
|
|
32
|
+
# must: {
|
|
33
|
+
# be_percentage: {
|
|
34
|
+
# is: ->(value:) { value.between?(0, 100) }
|
|
35
|
+
# }
|
|
36
|
+
# }
|
|
37
|
+
# end
|
|
38
|
+
# ```
|
|
39
|
+
class Must
|
|
40
|
+
extend Concerns::ErrorBuilder
|
|
41
|
+
|
|
42
|
+
# Validates all must conditions for an attribute.
|
|
43
|
+
#
|
|
44
|
+
# Iterates through check_options and validates each condition.
|
|
45
|
+
# Returns on first failure (early return pattern).
|
|
46
|
+
#
|
|
47
|
+
# @param context [Object] Service context for error message formatting
|
|
48
|
+
# @param attribute [Inputs::Input, Internals::Internal, Outputs::Output] Attribute to validate
|
|
49
|
+
# @param value [Object] Value to validate against conditions
|
|
50
|
+
# @param check_key [Symbol] Must be :must to trigger validation
|
|
51
|
+
# @param check_options [Hash{Symbol => Hash}] Named conditions with :is and :message
|
|
52
|
+
# @return [String, nil] Error message on first failure, nil if all pass
|
|
8
53
|
def self.check(context:, attribute:, value:, check_key:, check_options:)
|
|
9
54
|
return unless should_be_checked_for?(attribute, check_key)
|
|
10
55
|
|
|
11
|
-
|
|
56
|
+
check_options.each do |code, options|
|
|
57
|
+
error_message = validate_condition(context:, attribute:, value:, code:, options:)
|
|
58
|
+
return error_message if error_message.present?
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
nil
|
|
12
62
|
end
|
|
13
63
|
|
|
64
|
+
# Determines if validation should run for given attribute and check key.
|
|
65
|
+
#
|
|
66
|
+
# @param attribute [Inputs::Input, Internals::Internal, Outputs::Output] Attribute to check
|
|
67
|
+
# @param check_key [Symbol] Current validation check key
|
|
68
|
+
# @return [Boolean] true if this validator should run
|
|
14
69
|
def self.should_be_checked_for?(attribute, check_key)
|
|
15
70
|
check_key == :must && attribute.must_present?
|
|
16
71
|
end
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
next if message.blank?
|
|
34
|
-
|
|
35
|
-
add_error_with(message, code, reason, meta)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
errors
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
private
|
|
42
|
-
|
|
43
|
-
def call_or_fetch_message_from(code, options) # rubocop:disable Metrics/MethodLength
|
|
72
|
+
private_class_method :should_be_checked_for?
|
|
73
|
+
|
|
74
|
+
# Validates a single must condition by executing its check lambda.
|
|
75
|
+
#
|
|
76
|
+
# Executes the check lambda and handles three outcomes:
|
|
77
|
+
# - Lambda returns true: validation passes (returns nil)
|
|
78
|
+
# - Lambda returns [false, reason, meta]: validation fails with context
|
|
79
|
+
# - Lambda raises exception: returns syntax error message
|
|
80
|
+
#
|
|
81
|
+
# @param context [Object] Service context for error formatting
|
|
82
|
+
# @param attribute [Inputs::Input, Internals::Internal, Outputs::Output] Attribute being validated
|
|
83
|
+
# @param value [Object] Value to pass to check lambda
|
|
84
|
+
# @param code [Symbol] Condition identifier (e.g., :be_adult)
|
|
85
|
+
# @param options [Hash] Condition options with :is (lambda) and :message
|
|
86
|
+
# @return [String, nil] Error message on failure, nil on success
|
|
87
|
+
def self.validate_condition(context:, attribute:, value:, code:, options:) # rubocop:disable Metrics/MethodLength
|
|
44
88
|
check, message = options.values_at(:is, :message)
|
|
45
89
|
|
|
46
|
-
check_result, check_result_code, meta =
|
|
47
|
-
|
|
90
|
+
check_result, check_result_code, meta = call_check(
|
|
91
|
+
context:,
|
|
92
|
+
attribute:,
|
|
93
|
+
value:,
|
|
94
|
+
check:,
|
|
95
|
+
code:
|
|
96
|
+
)
|
|
48
97
|
|
|
49
|
-
|
|
98
|
+
# check_result is :syntax_error when syntax error occurred
|
|
99
|
+
return check_result_code if check_result == :syntax_error
|
|
100
|
+
return if check_result == true
|
|
50
101
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
102
|
+
build_error_message(
|
|
103
|
+
context:,
|
|
104
|
+
attribute:,
|
|
105
|
+
value:,
|
|
106
|
+
code:,
|
|
107
|
+
reason: check_result_code,
|
|
108
|
+
meta:,
|
|
109
|
+
message:
|
|
110
|
+
)
|
|
111
|
+
end
|
|
112
|
+
private_class_method :validate_condition
|
|
113
|
+
|
|
114
|
+
# Executes the check lambda with exception handling.
|
|
115
|
+
#
|
|
116
|
+
# Catches any StandardError from the lambda and converts it to a
|
|
117
|
+
# formatted syntax error message for better debugging experience.
|
|
118
|
+
#
|
|
119
|
+
# @param context [Object] Service context for error formatting
|
|
120
|
+
# @param attribute [Inputs::Input, Internals::Internal, Outputs::Output] Attribute being validated
|
|
121
|
+
# @param value [Object] Value to pass to lambda
|
|
122
|
+
# @param check [Proc] The validation lambda to execute
|
|
123
|
+
# @param code [Symbol] Condition identifier for error messages
|
|
124
|
+
# @return [Array] On success: [result, reason_code, meta_hash]
|
|
125
|
+
# @return [Array] On exception: [:syntax_error, error_message_string, nil]
|
|
126
|
+
def self.call_check(context:, attribute:, value:, check:, code:)
|
|
127
|
+
check.call(value:, **Servactory::Utils.fetch_hash_with_desired_attribute(attribute))
|
|
56
128
|
rescue StandardError => e
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
129
|
+
# Return formatted syntax error message
|
|
130
|
+
syntax_error_message = build_syntax_error_message(
|
|
131
|
+
context:,
|
|
132
|
+
attribute:,
|
|
133
|
+
value:,
|
|
134
|
+
code:,
|
|
135
|
+
exception_message: e.message
|
|
61
136
|
)
|
|
137
|
+
[:syntax_error, syntax_error_message, nil]
|
|
62
138
|
end
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
139
|
+
private_class_method :call_check
|
|
140
|
+
|
|
141
|
+
# Builds error message from validation failure.
|
|
142
|
+
#
|
|
143
|
+
# Uses custom message if provided, otherwise falls back to default.
|
|
144
|
+
# Message can be a String or Proc for dynamic formatting.
|
|
145
|
+
#
|
|
146
|
+
# NOTE: Errors from message.call are NOT caught - they propagate to caller.
|
|
147
|
+
#
|
|
148
|
+
# @param context [Object] Service context for message formatting
|
|
149
|
+
# @param attribute [Inputs::Input, Internals::Internal, Outputs::Output] Failed attribute
|
|
150
|
+
# @param value [Object] The invalid value
|
|
151
|
+
# @param code [Symbol] Condition identifier
|
|
152
|
+
# @param reason [Symbol, nil] Failure reason from check lambda
|
|
153
|
+
# @param meta [Hash, nil] Additional metadata from check lambda
|
|
154
|
+
# @param message [String, Proc, nil] Custom error message
|
|
155
|
+
# @return [String] Processed error message
|
|
156
|
+
def self.build_error_message(context:, attribute:, value:, code:, reason:, meta:, message:)
|
|
157
|
+
message = message.presence || Servactory::Maintenance::Attributes::Translator::Must.default_message
|
|
158
|
+
|
|
159
|
+
process_message(
|
|
160
|
+
message,
|
|
161
|
+
service: context.send(:servactory_service_info),
|
|
162
|
+
**Servactory::Utils.fetch_hash_with_desired_attribute(attribute),
|
|
163
|
+
value:,
|
|
72
164
|
code:,
|
|
73
165
|
reason:,
|
|
74
166
|
meta:
|
|
75
167
|
)
|
|
76
168
|
end
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
169
|
+
private_class_method :build_error_message
|
|
170
|
+
|
|
171
|
+
# Builds error message for exceptions raised in check lambdas.
|
|
172
|
+
#
|
|
173
|
+
# Formats the exception message with context for debugging,
|
|
174
|
+
# including the condition code and original exception text.
|
|
175
|
+
#
|
|
176
|
+
# @param context [Object] Service context for message formatting
|
|
177
|
+
# @param attribute [Inputs::Input, Internals::Internal, Outputs::Output] Attribute being validated
|
|
178
|
+
# @param value [Object] Value that caused the exception
|
|
179
|
+
# @param code [Symbol] Condition identifier where error occurred
|
|
180
|
+
# @param exception_message [String] Original exception message
|
|
181
|
+
# @return [String] Formatted syntax error message
|
|
182
|
+
def self.build_syntax_error_message(context:, attribute:, value:, code:, exception_message:)
|
|
183
|
+
message = Servactory::Maintenance::Attributes::Translator::Must.syntax_error_message
|
|
184
|
+
|
|
185
|
+
process_message(
|
|
186
|
+
message,
|
|
187
|
+
service: context.send(:servactory_service_info),
|
|
188
|
+
**Servactory::Utils.fetch_hash_with_desired_attribute(attribute),
|
|
189
|
+
value:,
|
|
84
190
|
code:,
|
|
85
191
|
exception_message:
|
|
86
192
|
)
|
|
87
193
|
end
|
|
194
|
+
private_class_method :build_syntax_error_message
|
|
88
195
|
end
|
|
89
196
|
end
|
|
90
197
|
end
|
|
@@ -4,13 +4,68 @@ module Servactory
|
|
|
4
4
|
module Maintenance
|
|
5
5
|
module Attributes
|
|
6
6
|
module Validations
|
|
7
|
-
|
|
7
|
+
# Validates that attribute values match their declared types.
|
|
8
|
+
#
|
|
9
|
+
# ## Purpose
|
|
10
|
+
#
|
|
11
|
+
# Type validator ensures attribute values conform to declared type
|
|
12
|
+
# constraints. It supports single types, union types (arrays), and
|
|
13
|
+
# custom type definitions. Works with inputs, internals, and outputs.
|
|
14
|
+
#
|
|
15
|
+
# ## Usage
|
|
16
|
+
#
|
|
17
|
+
# Type validation is automatic based on the `type` option:
|
|
18
|
+
#
|
|
19
|
+
# ```ruby
|
|
20
|
+
# class MyService < ApplicationService::Base
|
|
21
|
+
# input :id, type: Integer
|
|
22
|
+
# input :data, type: [Hash, Array] # union type
|
|
23
|
+
# input :status, type: String, required: false
|
|
24
|
+
#
|
|
25
|
+
# internal :result, type: CustomType
|
|
26
|
+
# output :response, type: Hash
|
|
27
|
+
# end
|
|
28
|
+
# ```
|
|
29
|
+
class Type
|
|
30
|
+
extend Concerns::ErrorBuilder
|
|
31
|
+
|
|
32
|
+
# Validates that a value matches the declared attribute types.
|
|
33
|
+
#
|
|
34
|
+
# @param context [Object] Service context for error formatting
|
|
35
|
+
# @param attribute [Inputs::Input, Internals::Internal, Outputs::Output] Attribute to validate
|
|
36
|
+
# @param value [Object] Value to check against declared types
|
|
37
|
+
# @param check_key [Symbol] Must be :types to trigger validation
|
|
38
|
+
# @return [String, nil] Error message on type mismatch, nil on success
|
|
8
39
|
def self.check(context:, attribute:, value:, check_key:, **)
|
|
9
40
|
return unless should_be_checked_for?(attribute, value, check_key)
|
|
10
41
|
|
|
11
|
-
|
|
42
|
+
prepared_value = compute_prepared_value(attribute, value)
|
|
43
|
+
|
|
44
|
+
error_data = Servactory::Maintenance::Validations::Types.validate(
|
|
45
|
+
context:,
|
|
46
|
+
attribute:,
|
|
47
|
+
types: attribute.types,
|
|
48
|
+
value: prepared_value
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
return if error_data.nil?
|
|
52
|
+
|
|
53
|
+
build_error_message(error_data)
|
|
12
54
|
end
|
|
13
55
|
|
|
56
|
+
# Determines if type validation should run for given attribute.
|
|
57
|
+
#
|
|
58
|
+
# Type validation runs when:
|
|
59
|
+
# - check_key is :types AND one of:
|
|
60
|
+
# - Input is required
|
|
61
|
+
# - Input is optional with non-nil default
|
|
62
|
+
# - Input is optional with non-nil value
|
|
63
|
+
# - Attribute is internal or output (always validated)
|
|
64
|
+
#
|
|
65
|
+
# @param attribute [Inputs::Input, Internals::Internal, Outputs::Output] Attribute to check
|
|
66
|
+
# @param value [Object] Current value (for optional input check)
|
|
67
|
+
# @param check_key [Symbol] Current validation check key
|
|
68
|
+
# @return [Boolean] true if type validation should run
|
|
14
69
|
# rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
15
70
|
def self.should_be_checked_for?(attribute, value, check_key)
|
|
16
71
|
check_key == :types && (
|
|
@@ -26,35 +81,30 @@ module Servactory
|
|
|
26
81
|
)
|
|
27
82
|
end
|
|
28
83
|
# rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
84
|
+
private_class_method :should_be_checked_for?
|
|
29
85
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
86
|
+
# Computes prepared value with default substitution for optional inputs.
|
|
87
|
+
#
|
|
88
|
+
# @param attribute [Inputs::Input, Internals::Internal, Outputs::Output] Attribute
|
|
89
|
+
# @param value [Object] Original value
|
|
90
|
+
# @return [Object] Prepared value (default or original)
|
|
91
|
+
def self.compute_prepared_value(attribute, value)
|
|
92
|
+
if attribute.input? && attribute.optional? && !attribute.default.nil? && value.blank?
|
|
93
|
+
attribute.default
|
|
94
|
+
else
|
|
95
|
+
value
|
|
96
|
+
end
|
|
36
97
|
end
|
|
98
|
+
private_class_method :compute_prepared_value
|
|
37
99
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
error_callback: ->(**args) { add_error(**args) }
|
|
45
|
-
)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
private
|
|
49
|
-
|
|
50
|
-
def prepared_value
|
|
51
|
-
@prepared_value ||=
|
|
52
|
-
if @attribute.input? && @attribute.optional? && !@attribute.default.nil? && @value.blank?
|
|
53
|
-
@attribute.default
|
|
54
|
-
else
|
|
55
|
-
@value
|
|
56
|
-
end
|
|
100
|
+
# Builds error message from validation error data.
|
|
101
|
+
#
|
|
102
|
+
# @param error_data [Hash] Error data from Types.validate
|
|
103
|
+
# @return [String] Processed error message
|
|
104
|
+
def self.build_error_message(error_data)
|
|
105
|
+
process_message(error_data[:message], **error_data)
|
|
57
106
|
end
|
|
107
|
+
private_class_method :build_error_message
|
|
58
108
|
end
|
|
59
109
|
end
|
|
60
110
|
end
|
|
@@ -4,44 +4,29 @@ module Servactory
|
|
|
4
4
|
module Maintenance
|
|
5
5
|
module Validations
|
|
6
6
|
class Types
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
7
|
+
# Validates value against expected types.
|
|
8
|
+
#
|
|
9
|
+
# Returns nil on success, error data Hash on failure.
|
|
10
|
+
#
|
|
11
|
+
# @param context [Object] Service context for error info
|
|
12
|
+
# @param attribute [Inputs::Input, Internals::Internal, Outputs::Output] Attribute being validated
|
|
13
|
+
# @param types [Array<Class, String, Symbol>] Expected type classes
|
|
14
|
+
# @param value [Object] Value to validate
|
|
15
|
+
# @return [Hash, nil] nil on success, error data Hash on failure
|
|
16
|
+
def self.validate(context:, attribute:, types:, value:) # rubocop:disable Metrics/MethodLength
|
|
17
|
+
prepared_types = types.map { |type| Servactory::Utils.constantize_class(type) }
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
return if prepared_types.any? do |type|
|
|
21
|
-
@value.is_a?(type)
|
|
22
|
-
end
|
|
19
|
+
return if prepared_types.any? { |type| value.is_a?(type) }
|
|
23
20
|
|
|
24
|
-
|
|
21
|
+
{
|
|
25
22
|
message: Servactory::Maintenance::Attributes::Translator::Type.default_message,
|
|
26
|
-
service:
|
|
27
|
-
attribute
|
|
28
|
-
value
|
|
23
|
+
service: context.send(:servactory_service_info),
|
|
24
|
+
attribute:,
|
|
25
|
+
value:,
|
|
29
26
|
key_name: nil,
|
|
30
27
|
expected_type: prepared_types.join(", "),
|
|
31
|
-
given_type:
|
|
32
|
-
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
private
|
|
36
|
-
|
|
37
|
-
def prepared_types
|
|
38
|
-
@prepared_types ||= prepared_types_from(@types)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def prepared_types_from(types)
|
|
42
|
-
types.map do |type|
|
|
43
|
-
Servactory::Utils.constantize_class(type)
|
|
44
|
-
end
|
|
28
|
+
given_type: value.class.name
|
|
29
|
+
}
|
|
45
30
|
end
|
|
46
31
|
end
|
|
47
32
|
end
|
|
@@ -12,24 +12,29 @@ module Servactory
|
|
|
12
12
|
@name = output.name
|
|
13
13
|
@types = output.types
|
|
14
14
|
@options = output.options
|
|
15
|
+
@attribute = output
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def system_name
|
|
19
|
+
@attribute.system_name
|
|
20
|
+
end
|
|
15
21
|
|
|
16
|
-
|
|
22
|
+
def i18n_name
|
|
23
|
+
@attribute.i18n_name
|
|
17
24
|
end
|
|
18
25
|
|
|
19
|
-
|
|
26
|
+
# The methods below are required to support the internal work.
|
|
20
27
|
|
|
21
|
-
def
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
28
|
+
def input?
|
|
29
|
+
false
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def internal?
|
|
33
|
+
false
|
|
34
|
+
end
|
|
29
35
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
end
|
|
36
|
+
def output?
|
|
37
|
+
true
|
|
33
38
|
end
|
|
34
39
|
end
|
|
35
40
|
|