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
|