servactory 2.12.0.rc2 → 2.12.0.rc3
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/config/locales/en.yml +12 -6
- data/config/locales/ru.yml +12 -6
- data/lib/servactory/configuration/setup.rb +3 -0
- data/lib/servactory/context/workspace/inputs.rb +0 -35
- data/lib/servactory/inputs/dsl.rb +0 -1
- data/lib/servactory/inputs/input.rb +0 -4
- data/lib/servactory/internals/dsl.rb +0 -1
- data/lib/servactory/internals/internal.rb +0 -4
- data/lib/servactory/maintenance/attributes/option.rb +7 -13
- data/lib/servactory/maintenance/attributes/options/registrar.rb +1 -23
- data/lib/servactory/maintenance/attributes/translator/must.rb +1 -1
- data/lib/servactory/maintenance/attributes/translator/type.rb +3 -38
- data/lib/servactory/maintenance/attributes/validations/must.rb +8 -6
- data/lib/servactory/maintenance/validations/types.rb +3 -26
- data/lib/servactory/outputs/dsl.rb +0 -1
- data/lib/servactory/outputs/output.rb +0 -4
- data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/consists_of_matcher.rb +9 -26
- data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/inclusion_matcher.rb +11 -27
- data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/message_matcher.rb +91 -0
- data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/must_matcher.rb +6 -0
- data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/schema_matcher.rb +83 -0
- data/lib/servactory/test_kit/rspec/matchers/have_service_input_matcher.rb +30 -11
- data/lib/servactory/test_kit/rspec/matchers/have_service_input_matchers/valid_with_matcher.rb +7 -1
- data/lib/servactory/test_kit/rspec/matchers/have_service_internal_matcher.rb +32 -11
- data/lib/servactory/tool_kit/dynamic_options/must.rb +29 -5
- data/lib/servactory/tool_kit/dynamic_options/schema.rb +193 -0
- data/lib/servactory/version.rb +1 -1
- metadata +5 -3
- data/lib/servactory/maintenance/validations/object_schema.rb +0 -116
@@ -0,0 +1,193 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module ToolKit
|
5
|
+
module DynamicOptions
|
6
|
+
class Schema < Must # rubocop:disable Metrics/ClassLength
|
7
|
+
RESERVED_ATTRIBUTES = %i[type required default].freeze
|
8
|
+
private_constant :RESERVED_ATTRIBUTES
|
9
|
+
|
10
|
+
def self.use(option_name = :schema, default_hash_mode_class_names:)
|
11
|
+
instance = new(option_name, :is, false)
|
12
|
+
instance.assign(default_hash_mode_class_names)
|
13
|
+
instance.must(:schema)
|
14
|
+
end
|
15
|
+
|
16
|
+
def assign(default_hash_mode_class_names)
|
17
|
+
@default_hash_mode_class_names = default_hash_mode_class_names
|
18
|
+
end
|
19
|
+
|
20
|
+
def condition_for_input_with(input:, value:, option:)
|
21
|
+
common_condition_with(attribute: input, value:, option:)
|
22
|
+
end
|
23
|
+
|
24
|
+
def condition_for_internal_with(internal:, value:, option:)
|
25
|
+
common_condition_with(attribute: internal, value:, option:)
|
26
|
+
end
|
27
|
+
|
28
|
+
def condition_for_output_with(output:, value:, option:)
|
29
|
+
common_condition_with(attribute: output, value:, option:)
|
30
|
+
end
|
31
|
+
|
32
|
+
def common_condition_with(attribute:, value:, option:)
|
33
|
+
return true if option.value == false
|
34
|
+
return [false, :wrong_type] if @default_hash_mode_class_names.intersection(attribute.types).empty?
|
35
|
+
|
36
|
+
schema = option.value.fetch(:is, option.value)
|
37
|
+
|
38
|
+
is_success, reason, meta = validate_for!(object: value, schema:)
|
39
|
+
|
40
|
+
prepare_object_with!(object: value, schema:) if is_success
|
41
|
+
|
42
|
+
[is_success, reason, meta]
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate_for!(object:, schema:, root_schema_key: nil) # rubocop:disable Metrics/MethodLength
|
46
|
+
unless object.respond_to?(:fetch)
|
47
|
+
return [
|
48
|
+
false,
|
49
|
+
:wrong_element_value,
|
50
|
+
{
|
51
|
+
key_name: root_schema_key,
|
52
|
+
expected_type: Hash.name,
|
53
|
+
given_type: object.class.name
|
54
|
+
}
|
55
|
+
]
|
56
|
+
end
|
57
|
+
|
58
|
+
errors = schema.map do |schema_key, schema_value|
|
59
|
+
attribute_type = schema_value.fetch(:type, String)
|
60
|
+
|
61
|
+
if attribute_type == Hash
|
62
|
+
validate_for!(
|
63
|
+
object: object.fetch(schema_key, {}),
|
64
|
+
schema: schema_value.except(*RESERVED_ATTRIBUTES),
|
65
|
+
root_schema_key: schema_key
|
66
|
+
)
|
67
|
+
else
|
68
|
+
is_success, given_type = validate_with(
|
69
|
+
object:,
|
70
|
+
schema_key:,
|
71
|
+
schema_value:,
|
72
|
+
attribute_type:,
|
73
|
+
attribute_required: schema_value.fetch(:required, true)
|
74
|
+
)
|
75
|
+
|
76
|
+
next if is_success
|
77
|
+
|
78
|
+
[false, :wrong_element_type, { key_name: schema_key, expected_type: attribute_type, given_type: }]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
errors.compact.first || true
|
83
|
+
end
|
84
|
+
|
85
|
+
def validate_with(object:, schema_key:, schema_value:, attribute_type:, attribute_required:) # rubocop:disable Metrics/MethodLength
|
86
|
+
unless should_be_checked_for?(
|
87
|
+
object:,
|
88
|
+
schema_key:,
|
89
|
+
schema_value:,
|
90
|
+
required: attribute_required
|
91
|
+
) # do
|
92
|
+
return true
|
93
|
+
end
|
94
|
+
|
95
|
+
value = object.fetch(schema_key, nil)
|
96
|
+
prepared_value = prepare_value_from(schema_value:, value:, required: attribute_required)
|
97
|
+
|
98
|
+
[
|
99
|
+
Array(attribute_type).uniq.any? { |type| prepared_value.is_a?(type) },
|
100
|
+
prepared_value.class.name
|
101
|
+
]
|
102
|
+
end
|
103
|
+
|
104
|
+
def should_be_checked_for?(object:, schema_key:, schema_value:, required:)
|
105
|
+
required || (
|
106
|
+
!required && !fetch_default_from(schema_value).nil?
|
107
|
+
) || (
|
108
|
+
!required && !object.fetch(schema_key, nil).nil?
|
109
|
+
)
|
110
|
+
end
|
111
|
+
|
112
|
+
def prepare_value_from(schema_value:, value:, required:)
|
113
|
+
if !required && !fetch_default_from(schema_value).nil? && value.blank?
|
114
|
+
fetch_default_from(schema_value)
|
115
|
+
else
|
116
|
+
value
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def fetch_default_from(value)
|
121
|
+
value.fetch(:default, nil)
|
122
|
+
end
|
123
|
+
|
124
|
+
########################################################################
|
125
|
+
|
126
|
+
def prepare_object_with!(object:, schema:) # rubocop:disable Metrics/MethodLength
|
127
|
+
schema.map do |schema_key, schema_value|
|
128
|
+
attribute_type = schema_value.fetch(:type, String)
|
129
|
+
|
130
|
+
if attribute_type == Hash
|
131
|
+
prepare_object_with!(
|
132
|
+
object: object.fetch(schema_key, {}),
|
133
|
+
schema: schema_value.except(*RESERVED_ATTRIBUTES)
|
134
|
+
)
|
135
|
+
else
|
136
|
+
next object unless object[schema_key].nil?
|
137
|
+
|
138
|
+
next object if (default = schema_value.fetch(:default, nil)).nil?
|
139
|
+
|
140
|
+
object[schema_key] = default
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
########################################################################
|
146
|
+
########################################################################
|
147
|
+
########################################################################
|
148
|
+
|
149
|
+
def message_for_input_with(service:, input:, reason:, meta:, **)
|
150
|
+
i18n_key = "inputs.validations.must.dynamic_options.schema"
|
151
|
+
i18n_key += reason.present? ? ".#{reason}" : ".default"
|
152
|
+
|
153
|
+
service.translate(
|
154
|
+
i18n_key,
|
155
|
+
service_class_name: service.class_name,
|
156
|
+
input_name: input.name,
|
157
|
+
key_name: meta.fetch(:key_name),
|
158
|
+
expected_type: meta.fetch(:expected_type),
|
159
|
+
given_type: meta.fetch(:given_type)
|
160
|
+
)
|
161
|
+
end
|
162
|
+
|
163
|
+
def message_for_internal_with(service:, internal:, reason:, meta:, **)
|
164
|
+
i18n_key = "internals.validations.must.dynamic_options.schema"
|
165
|
+
i18n_key += reason.present? ? ".#{reason}" : ".default"
|
166
|
+
|
167
|
+
service.translate(
|
168
|
+
i18n_key,
|
169
|
+
service_class_name: service.class_name,
|
170
|
+
internal_name: internal.name,
|
171
|
+
key_name: meta.fetch(:key_name),
|
172
|
+
expected_type: meta.fetch(:expected_type),
|
173
|
+
given_type: meta.fetch(:given_type)
|
174
|
+
)
|
175
|
+
end
|
176
|
+
|
177
|
+
def message_for_output_with(service:, output:, reason:, meta:, **)
|
178
|
+
i18n_key = "outputs.validations.must.dynamic_options.schema"
|
179
|
+
i18n_key += reason.present? ? ".#{reason}" : ".default"
|
180
|
+
|
181
|
+
service.translate(
|
182
|
+
i18n_key,
|
183
|
+
service_class_name: service.class_name,
|
184
|
+
output_name: output.name,
|
185
|
+
key_name: meta.fetch(:key_name),
|
186
|
+
expected_type: meta.fetch(:expected_type),
|
187
|
+
given_type: meta.fetch(:given_type)
|
188
|
+
)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
data/lib/servactory/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: servactory
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.12.0.
|
4
|
+
version: 2.12.0.rc3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anton Sokolov
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-03-01 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: activesupport
|
@@ -298,7 +298,6 @@ files:
|
|
298
298
|
- lib/servactory/maintenance/attributes/validations/errors.rb
|
299
299
|
- lib/servactory/maintenance/attributes/validations/must.rb
|
300
300
|
- lib/servactory/maintenance/attributes/validations/type.rb
|
301
|
-
- lib/servactory/maintenance/validations/object_schema.rb
|
302
301
|
- lib/servactory/maintenance/validations/types.rb
|
303
302
|
- lib/servactory/outputs/collection.rb
|
304
303
|
- lib/servactory/outputs/dsl.rb
|
@@ -310,7 +309,9 @@ files:
|
|
310
309
|
- lib/servactory/test_kit/rspec/matchers.rb
|
311
310
|
- lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/consists_of_matcher.rb
|
312
311
|
- lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/inclusion_matcher.rb
|
312
|
+
- lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/message_matcher.rb
|
313
313
|
- lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/must_matcher.rb
|
314
|
+
- lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/schema_matcher.rb
|
314
315
|
- lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/types_matcher.rb
|
315
316
|
- lib/servactory/test_kit/rspec/matchers/have_service_input_matcher.rb
|
316
317
|
- lib/servactory/test_kit/rspec/matchers/have_service_input_matchers/default_matcher.rb
|
@@ -326,6 +327,7 @@ files:
|
|
326
327
|
- lib/servactory/tool_kit/dynamic_options/min.rb
|
327
328
|
- lib/servactory/tool_kit/dynamic_options/multiple_of.rb
|
328
329
|
- lib/servactory/tool_kit/dynamic_options/must.rb
|
330
|
+
- lib/servactory/tool_kit/dynamic_options/schema.rb
|
329
331
|
- lib/servactory/utils.rb
|
330
332
|
- lib/servactory/version.rb
|
331
333
|
homepage: https://github.com/servactory/servactory
|
@@ -1,116 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Servactory
|
4
|
-
module Maintenance
|
5
|
-
module Validations
|
6
|
-
class ObjectSchema
|
7
|
-
RESERVED_ATTRIBUTES = %i[type required default].freeze
|
8
|
-
private_constant :RESERVED_ATTRIBUTES
|
9
|
-
|
10
|
-
attr_reader :errors
|
11
|
-
|
12
|
-
def self.validate(...)
|
13
|
-
new(...).validate
|
14
|
-
end
|
15
|
-
|
16
|
-
def initialize(object:, schema:)
|
17
|
-
@object = object
|
18
|
-
@schema = schema.fetch(:is)
|
19
|
-
|
20
|
-
@errors = []
|
21
|
-
end
|
22
|
-
|
23
|
-
def validate
|
24
|
-
validate_for!(object: @object, schema: @schema)
|
25
|
-
|
26
|
-
self
|
27
|
-
end
|
28
|
-
|
29
|
-
def valid?
|
30
|
-
@errors.empty?
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def validate_for!(object:, schema:, root_schema_key: nil) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
36
|
-
unless object.respond_to?(:fetch)
|
37
|
-
add_error(key_name: root_schema_key, expected_type: Hash.name, given_type: object.class.name)
|
38
|
-
return
|
39
|
-
end
|
40
|
-
|
41
|
-
schema.each do |schema_key, schema_value|
|
42
|
-
attribute_type = schema_value.fetch(:type, String)
|
43
|
-
|
44
|
-
if attribute_type == Hash
|
45
|
-
validate_for!(
|
46
|
-
object: object.fetch(schema_key, {}),
|
47
|
-
schema: schema_value.except(*RESERVED_ATTRIBUTES),
|
48
|
-
root_schema_key: schema_key
|
49
|
-
)
|
50
|
-
else
|
51
|
-
is_success = validate_with(
|
52
|
-
object:,
|
53
|
-
schema_key:,
|
54
|
-
schema_value:,
|
55
|
-
attribute_type:,
|
56
|
-
attribute_required: schema_value.fetch(:required, true)
|
57
|
-
)
|
58
|
-
|
59
|
-
next if is_success
|
60
|
-
|
61
|
-
add_error(
|
62
|
-
key_name: schema_key,
|
63
|
-
expected_type: attribute_type,
|
64
|
-
given_type: object.fetch(schema_key, nil).class.name
|
65
|
-
)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def validate_with(object:, schema_key:, schema_value:, attribute_type:, attribute_required:) # rubocop:disable Metrics/MethodLength
|
71
|
-
unless should_be_checked_for?(
|
72
|
-
object:,
|
73
|
-
schema_key:,
|
74
|
-
schema_value:,
|
75
|
-
required: attribute_required
|
76
|
-
) # do
|
77
|
-
return true
|
78
|
-
end
|
79
|
-
|
80
|
-
value = object.fetch(schema_key, nil)
|
81
|
-
prepared_value = prepare_value_from(schema_value:, value:, required: attribute_required)
|
82
|
-
|
83
|
-
Array(attribute_type).uniq.any? { |type| prepared_value.is_a?(type) }
|
84
|
-
end
|
85
|
-
|
86
|
-
def should_be_checked_for?(object:, schema_key:, schema_value:, required:)
|
87
|
-
required || (
|
88
|
-
!required && !fetch_default_from(schema_value).nil?
|
89
|
-
) || (
|
90
|
-
!required && !object.fetch(schema_key, nil).nil?
|
91
|
-
)
|
92
|
-
end
|
93
|
-
|
94
|
-
def prepare_value_from(schema_value:, value:, required:)
|
95
|
-
if !required && !fetch_default_from(schema_value).nil? && value.blank?
|
96
|
-
fetch_default_from(schema_value)
|
97
|
-
else
|
98
|
-
value
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
def fetch_default_from(value)
|
103
|
-
value.fetch(:default, nil)
|
104
|
-
end
|
105
|
-
|
106
|
-
def add_error(key_name:, expected_type:, given_type:)
|
107
|
-
@errors << {
|
108
|
-
key_name:,
|
109
|
-
expected_type:,
|
110
|
-
given_type:
|
111
|
-
}
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|