schemacop 2.4.5 → 3.0.0.rc2
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/.gitignore +3 -0
- data/.rubocop.yml +25 -1
- data/.travis.yml +3 -1
- data/CHANGELOG.md +32 -1
- data/README.md +53 -710
- data/README_V2.md +775 -0
- data/README_V3.md +1195 -0
- data/Rakefile +8 -12
- data/VERSION +1 -1
- data/lib/schemacop.rb +35 -36
- data/lib/schemacop/base_schema.rb +37 -0
- data/lib/schemacop/railtie.rb +10 -0
- data/lib/schemacop/schema.rb +1 -60
- data/lib/schemacop/schema2.rb +22 -0
- data/lib/schemacop/schema3.rb +21 -0
- data/lib/schemacop/scoped_env.rb +25 -13
- data/lib/schemacop/v2.rb +26 -0
- data/lib/schemacop/{caster.rb → v2/caster.rb} +16 -2
- data/lib/schemacop/{collector.rb → v2/collector.rb} +5 -2
- data/lib/schemacop/{dupper.rb → v2/dupper.rb} +1 -1
- data/lib/schemacop/{field_node.rb → v2/field_node.rb} +4 -3
- data/lib/schemacop/v2/node.rb +142 -0
- data/lib/schemacop/{node_resolver.rb → v2/node_resolver.rb} +1 -1
- data/lib/schemacop/v2/node_supporting_field.rb +70 -0
- data/lib/schemacop/{node_supporting_type.rb → v2/node_supporting_type.rb} +14 -11
- data/lib/schemacop/{node_with_block.rb → v2/node_with_block.rb} +3 -2
- data/lib/schemacop/v2/root_node.rb +6 -0
- data/lib/schemacop/v2/validator/array_validator.rb +32 -0
- data/lib/schemacop/{validator → v2/validator}/boolean_validator.rb +1 -1
- data/lib/schemacop/v2/validator/float_validator.rb +7 -0
- data/lib/schemacop/v2/validator/hash_validator.rb +37 -0
- data/lib/schemacop/v2/validator/integer_validator.rb +7 -0
- data/lib/schemacop/{validator → v2/validator}/nil_validator.rb +1 -1
- data/lib/schemacop/v2/validator/number_validator.rb +21 -0
- data/lib/schemacop/v2/validator/object_validator.rb +29 -0
- data/lib/schemacop/v2/validator/string_validator.rb +39 -0
- data/lib/schemacop/{validator → v2/validator}/symbol_validator.rb +1 -1
- data/lib/schemacop/v3.rb +45 -0
- data/lib/schemacop/v3/all_of_node.rb +27 -0
- data/lib/schemacop/v3/any_of_node.rb +28 -0
- data/lib/schemacop/v3/array_node.rb +218 -0
- data/lib/schemacop/v3/boolean_node.rb +16 -0
- data/lib/schemacop/v3/combination_node.rb +45 -0
- data/lib/schemacop/v3/context.rb +17 -0
- data/lib/schemacop/v3/dsl_scope.rb +46 -0
- data/lib/schemacop/v3/global_context.rb +114 -0
- data/lib/schemacop/v3/hash_node.rb +256 -0
- data/lib/schemacop/v3/integer_node.rb +13 -0
- data/lib/schemacop/v3/is_not_node.rb +32 -0
- data/lib/schemacop/v3/node.rb +215 -0
- data/lib/schemacop/v3/node_registry.rb +49 -0
- data/lib/schemacop/v3/number_node.rb +18 -0
- data/lib/schemacop/v3/numeric_node.rb +76 -0
- data/lib/schemacop/v3/object_node.rb +40 -0
- data/lib/schemacop/v3/one_of_node.rb +28 -0
- data/lib/schemacop/v3/reference_node.rb +49 -0
- data/lib/schemacop/v3/result.rb +58 -0
- data/lib/schemacop/v3/string_node.rb +124 -0
- data/lib/schemacop/v3/symbol_node.rb +13 -0
- data/schemacop.gemspec +24 -27
- data/test/lib/test_helper.rb +152 -0
- data/test/schemas/nested/group.rb +6 -0
- data/test/schemas/user.rb +7 -0
- data/test/unit/schemacop/v2/casting_test.rb +120 -0
- data/test/unit/schemacop/v2/collector_test.rb +47 -0
- data/test/unit/schemacop/v2/custom_check_test.rb +95 -0
- data/test/unit/schemacop/v2/custom_if_test.rb +97 -0
- data/test/unit/schemacop/v2/defaults_test.rb +95 -0
- data/test/unit/schemacop/v2/empty_test.rb +16 -0
- data/test/unit/schemacop/v2/nil_dis_allow_test.rb +43 -0
- data/test/unit/schemacop/v2/node_resolver_test.rb +28 -0
- data/test/unit/schemacop/v2/short_forms_test.rb +351 -0
- data/test/unit/schemacop/v2/types_test.rb +88 -0
- data/test/unit/schemacop/v2/validator_array_test.rb +99 -0
- data/test/unit/schemacop/v2/validator_boolean_test.rb +17 -0
- data/test/unit/schemacop/v2/validator_float_test.rb +59 -0
- data/test/unit/schemacop/v2/validator_hash_test.rb +95 -0
- data/test/unit/schemacop/v2/validator_integer_test.rb +48 -0
- data/test/unit/schemacop/v2/validator_nil_test.rb +15 -0
- data/test/unit/schemacop/v2/validator_number_test.rb +62 -0
- data/test/unit/schemacop/v2/validator_object_test.rb +141 -0
- data/test/unit/schemacop/v2/validator_string_test.rb +78 -0
- data/test/unit/schemacop/v2/validator_symbol_test.rb +18 -0
- data/test/unit/schemacop/v3/all_of_node_test.rb +198 -0
- data/test/unit/schemacop/v3/any_of_node_test.rb +218 -0
- data/test/unit/schemacop/v3/array_node_test.rb +815 -0
- data/test/unit/schemacop/v3/boolean_node_test.rb +126 -0
- data/test/unit/schemacop/v3/global_context_test.rb +164 -0
- data/test/unit/schemacop/v3/hash_node_test.rb +884 -0
- data/test/unit/schemacop/v3/integer_node_test.rb +323 -0
- data/test/unit/schemacop/v3/is_not_node_test.rb +173 -0
- data/test/unit/schemacop/v3/node_test.rb +148 -0
- data/test/unit/schemacop/v3/number_node_test.rb +292 -0
- data/test/unit/schemacop/v3/object_node_test.rb +170 -0
- data/test/unit/schemacop/v3/one_of_node_test.rb +187 -0
- data/test/unit/schemacop/v3/reference_node_test.rb +351 -0
- data/test/unit/schemacop/v3/string_node_test.rb +334 -0
- data/test/unit/schemacop/v3/symbol_node_test.rb +75 -0
- metadata +152 -145
- data/doc/Schemacop.html +0 -146
- data/doc/Schemacop/ArrayValidator.html +0 -329
- data/doc/Schemacop/BooleanValidator.html +0 -145
- data/doc/Schemacop/Caster.html +0 -379
- data/doc/Schemacop/Collector.html +0 -787
- data/doc/Schemacop/Dupper.html +0 -214
- data/doc/Schemacop/Exceptions.html +0 -115
- data/doc/Schemacop/Exceptions/InvalidSchemaError.html +0 -124
- data/doc/Schemacop/Exceptions/ValidationError.html +0 -124
- data/doc/Schemacop/FieldNode.html +0 -421
- data/doc/Schemacop/FloatValidator.html +0 -158
- data/doc/Schemacop/HashValidator.html +0 -293
- data/doc/Schemacop/IntegerValidator.html +0 -158
- data/doc/Schemacop/NilValidator.html +0 -145
- data/doc/Schemacop/Node.html +0 -1438
- data/doc/Schemacop/NodeResolver.html +0 -258
- data/doc/Schemacop/NodeSupportingField.html +0 -590
- data/doc/Schemacop/NodeSupportingType.html +0 -612
- data/doc/Schemacop/NodeWithBlock.html +0 -289
- data/doc/Schemacop/NumberValidator.html +0 -232
- data/doc/Schemacop/ObjectValidator.html +0 -298
- data/doc/Schemacop/RootNode.html +0 -171
- data/doc/Schemacop/Schema.html +0 -699
- data/doc/Schemacop/StringValidator.html +0 -295
- data/doc/Schemacop/SymbolValidator.html +0 -145
- data/doc/ScopedEnv.html +0 -351
- data/doc/_index.html +0 -379
- data/doc/class_list.html +0 -51
- data/doc/css/common.css +0 -1
- data/doc/css/full_list.css +0 -58
- data/doc/css/style.css +0 -496
- data/doc/file.README.html +0 -833
- data/doc/file_list.html +0 -56
- data/doc/frames.html +0 -17
- data/doc/index.html +0 -833
- data/doc/inheritance.graphml +0 -524
- data/doc/inheritance.pdf +0 -825
- data/doc/js/app.js +0 -303
- data/doc/js/full_list.js +0 -216
- data/doc/js/jquery.js +0 -4
- data/doc/method_list.html +0 -587
- data/doc/top-level-namespace.html +0 -112
- data/lib/schemacop/node.rb +0 -139
- data/lib/schemacop/node_supporting_field.rb +0 -58
- data/lib/schemacop/root_node.rb +0 -4
- data/lib/schemacop/validator/array_validator.rb +0 -30
- data/lib/schemacop/validator/float_validator.rb +0 -5
- data/lib/schemacop/validator/hash_validator.rb +0 -35
- data/lib/schemacop/validator/integer_validator.rb +0 -5
- data/lib/schemacop/validator/number_validator.rb +0 -19
- data/lib/schemacop/validator/object_validator.rb +0 -27
- data/lib/schemacop/validator/string_validator.rb +0 -37
- data/test/casting_test.rb +0 -90
- data/test/collector_test.rb +0 -45
- data/test/custom_check_test.rb +0 -93
- data/test/custom_if_test.rb +0 -95
- data/test/defaults_test.rb +0 -93
- data/test/empty_test.rb +0 -14
- data/test/nil_dis_allow_test.rb +0 -41
- data/test/node_resolver_test.rb +0 -26
- data/test/short_forms_test.rb +0 -349
- data/test/test_helper.rb +0 -13
- data/test/types_test.rb +0 -84
- data/test/validator_array_test.rb +0 -97
- data/test/validator_boolean_test.rb +0 -15
- data/test/validator_float_test.rb +0 -57
- data/test/validator_hash_test.rb +0 -93
- data/test/validator_integer_test.rb +0 -46
- data/test/validator_nil_test.rb +0 -13
- data/test/validator_number_test.rb +0 -60
- data/test/validator_object_test.rb +0 -139
- data/test/validator_string_test.rb +0 -76
- data/test/validator_symbol_test.rb +0 -16
@@ -0,0 +1,215 @@
|
|
1
|
+
module Schemacop
|
2
|
+
module V3
|
3
|
+
class Node
|
4
|
+
attr_reader :name
|
5
|
+
attr_reader :default
|
6
|
+
attr_reader :title
|
7
|
+
attr_reader :description
|
8
|
+
attr_reader :options
|
9
|
+
attr_reader :parent
|
10
|
+
|
11
|
+
class_attribute :_supports_children
|
12
|
+
self._supports_children = nil
|
13
|
+
|
14
|
+
def self.supports_children(name: false)
|
15
|
+
self._supports_children = { name: name }
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.supports_children_options
|
19
|
+
_supports_children
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.resolve_class(type)
|
23
|
+
NodeRegistry.find(type)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.create(type = self, **options, &block)
|
27
|
+
klass = resolve_class(type)
|
28
|
+
fail "Could not find node for type #{type.inspect}." unless klass
|
29
|
+
|
30
|
+
node = klass.new(**options, &block)
|
31
|
+
|
32
|
+
if options.delete(:cast_str)
|
33
|
+
format = NodeRegistry.name(klass)
|
34
|
+
one_of_options = {
|
35
|
+
required: options.delete(:required),
|
36
|
+
name: options.delete(:name)
|
37
|
+
}
|
38
|
+
node = create(:one_of, **one_of_options) do
|
39
|
+
self.node node
|
40
|
+
str format: format, format_options: options
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
return node
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.allowed_options
|
48
|
+
%i[name required default description examples enum parent options cast_str title]
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.dsl_methods
|
52
|
+
%i[dsl_scm dsl_node]
|
53
|
+
end
|
54
|
+
|
55
|
+
def allowed_types
|
56
|
+
{}
|
57
|
+
end
|
58
|
+
|
59
|
+
def used_external_schemas
|
60
|
+
children.map(&:used_external_schemas).flatten.uniq
|
61
|
+
end
|
62
|
+
|
63
|
+
def children
|
64
|
+
[]
|
65
|
+
end
|
66
|
+
|
67
|
+
def initialize(**options, &block)
|
68
|
+
# Check options #
|
69
|
+
disallowed_options = options.keys - self.class.allowed_options
|
70
|
+
|
71
|
+
if disallowed_options.any?
|
72
|
+
fail "Options #{disallowed_options.inspect} are not allowed for this node."
|
73
|
+
end
|
74
|
+
|
75
|
+
# Assign attributes #
|
76
|
+
@name = options.delete(:name)
|
77
|
+
@name = @name.to_s unless @name.nil? || @name.is_a?(Regexp)
|
78
|
+
@required = !!options.delete(:required)
|
79
|
+
@default = options.delete(:default)
|
80
|
+
@title = options.delete(:title)
|
81
|
+
@description = options.delete(:description)
|
82
|
+
@examples = options.delete(:examples)
|
83
|
+
@enum = options.delete(:enum)&.to_set
|
84
|
+
@parent = options.delete(:parent)
|
85
|
+
@options = options
|
86
|
+
@schemas = {}
|
87
|
+
|
88
|
+
# Run subclass init #
|
89
|
+
init
|
90
|
+
|
91
|
+
# Run DSL block #
|
92
|
+
if block_given?
|
93
|
+
unless self.class.supports_children_options
|
94
|
+
fail "Node #{self.class} does not support blocks."
|
95
|
+
end
|
96
|
+
|
97
|
+
scope = DslScope.new(self)
|
98
|
+
env = ScopedEnv.new(self, self.class.dsl_methods, scope, :dsl_)
|
99
|
+
env.instance_exec(&block)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Validate self #
|
103
|
+
begin
|
104
|
+
validate_self
|
105
|
+
rescue StandardError => e
|
106
|
+
fail Exceptions::InvalidSchemaError, e.message
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def create(type, **options, &block)
|
111
|
+
options[:parent] = self
|
112
|
+
return Node.create(type, **options, &block)
|
113
|
+
end
|
114
|
+
|
115
|
+
def init; end
|
116
|
+
|
117
|
+
def dsl_scm(name, type = :hash, **options, &block)
|
118
|
+
@schemas[name] = create(type, **options, &block)
|
119
|
+
end
|
120
|
+
|
121
|
+
def dsl_node(node, *_args, **_kwargs)
|
122
|
+
add_child node
|
123
|
+
end
|
124
|
+
|
125
|
+
def schemas
|
126
|
+
(parent&.schemas || {}).merge(@schemas)
|
127
|
+
end
|
128
|
+
|
129
|
+
def required?
|
130
|
+
@required
|
131
|
+
end
|
132
|
+
|
133
|
+
def as_json
|
134
|
+
process_json([], {})
|
135
|
+
end
|
136
|
+
|
137
|
+
def cast(value)
|
138
|
+
value || default
|
139
|
+
end
|
140
|
+
|
141
|
+
def validate(data)
|
142
|
+
result = Result.new(self, data)
|
143
|
+
_validate(data, result: result)
|
144
|
+
return result
|
145
|
+
end
|
146
|
+
|
147
|
+
protected
|
148
|
+
|
149
|
+
def item_matches?(item, data)
|
150
|
+
item_result = Result.new(self)
|
151
|
+
item._validate(data, result: item_result)
|
152
|
+
return item_result.errors.none?
|
153
|
+
end
|
154
|
+
|
155
|
+
def process_json(attrs, json)
|
156
|
+
if @schemas.any?
|
157
|
+
json[:definitions] = {}
|
158
|
+
@schemas.each do |name, subschema|
|
159
|
+
json[:definitions][name] = subschema.as_json
|
160
|
+
end
|
161
|
+
end
|
162
|
+
attrs.each do |attr|
|
163
|
+
if options.include?(attr)
|
164
|
+
json[attr.to_s.camelize(:lower).to_sym] = options[attr]
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
json[:title] = @title if @title
|
169
|
+
json[:examples] = @examples if @examples
|
170
|
+
json[:description] = @description if @description
|
171
|
+
json[:default] = @default if @default
|
172
|
+
json[:enum] = @enum.to_a if @enum
|
173
|
+
|
174
|
+
return json.as_json
|
175
|
+
end
|
176
|
+
|
177
|
+
def type_assertion_method
|
178
|
+
:is_a?
|
179
|
+
end
|
180
|
+
|
181
|
+
def _validate(data, result:)
|
182
|
+
# Validate nil #
|
183
|
+
if data.nil? && required?
|
184
|
+
result.error 'Value must be given.'
|
185
|
+
return nil
|
186
|
+
end
|
187
|
+
|
188
|
+
# Apply default #
|
189
|
+
if data.nil?
|
190
|
+
if default
|
191
|
+
data = default
|
192
|
+
else
|
193
|
+
return nil
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
# Validate type #
|
198
|
+
if allowed_types.any? && allowed_types.keys.none? { |c| data.send(type_assertion_method, c) }
|
199
|
+
collection = allowed_types.values.map { |t| "\"#{t}\"" }.uniq.sort.join(' or ')
|
200
|
+
result.error %(Invalid type, expected #{collection}.)
|
201
|
+
return nil
|
202
|
+
end
|
203
|
+
|
204
|
+
# Validate enums #
|
205
|
+
if @enum && !@enum.include?(data)
|
206
|
+
result.error "Value not included in enum #{@enum.to_a.inspect}."
|
207
|
+
end
|
208
|
+
|
209
|
+
return data
|
210
|
+
end
|
211
|
+
|
212
|
+
def validate_self; end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Schemacop
|
2
|
+
module V3
|
3
|
+
class NodeRegistry
|
4
|
+
@by_name = {}
|
5
|
+
@by_short_name = {}
|
6
|
+
@by_class = {}
|
7
|
+
|
8
|
+
def self.register(name, short_name, klass)
|
9
|
+
@by_name[name.to_sym] = klass
|
10
|
+
@by_short_name[short_name.to_sym] = klass
|
11
|
+
@by_class[klass] = { name: name.to_sym, short_name: short_name.to_sym }
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.dsl_methods(bang)
|
15
|
+
return @by_short_name.keys.map do |short_name|
|
16
|
+
if bang
|
17
|
+
["dsl_#{short_name}!", "dsl_#{short_name}?"]
|
18
|
+
else
|
19
|
+
["dsl_#{short_name}"]
|
20
|
+
end
|
21
|
+
end.flatten.map(&:to_sym)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.find(name_or_klass)
|
25
|
+
if name_or_klass.is_a?(Class)
|
26
|
+
return name_or_klass
|
27
|
+
else
|
28
|
+
return by_name(name_or_klass)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.by_name(name)
|
33
|
+
@by_name[name.to_sym]
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.by_short_name(short_name)
|
37
|
+
@by_short_name[short_name.to_sym]
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.name(klass)
|
41
|
+
@by_class[klass][:name]
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.short_name(klass)
|
45
|
+
@by_class[klass][:short_name]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Schemacop
|
2
|
+
module V3
|
3
|
+
class NumberNode < NumericNode
|
4
|
+
def as_json
|
5
|
+
process_json(ATTRIBUTES, type: :number)
|
6
|
+
end
|
7
|
+
|
8
|
+
def allowed_types
|
9
|
+
{
|
10
|
+
Integer => :integer,
|
11
|
+
Float => :float,
|
12
|
+
Rational => :rational,
|
13
|
+
BigDecimal => :big_decimal
|
14
|
+
}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Schemacop
|
2
|
+
module V3
|
3
|
+
# @abstract
|
4
|
+
class NumericNode < Node
|
5
|
+
ATTRIBUTES = %i[
|
6
|
+
minimum
|
7
|
+
exclusive_minimum
|
8
|
+
maximum
|
9
|
+
exclusive_maximum
|
10
|
+
multiple_of
|
11
|
+
].freeze
|
12
|
+
|
13
|
+
def self.allowed_options
|
14
|
+
super + ATTRIBUTES
|
15
|
+
end
|
16
|
+
|
17
|
+
def _validate(data, result:)
|
18
|
+
super_data = super
|
19
|
+
return if super_data.nil?
|
20
|
+
|
21
|
+
# Validate minimum #
|
22
|
+
if options[:minimum] && super_data < options[:minimum]
|
23
|
+
result.error "Value must have a minimum of #{options[:minimum]}."
|
24
|
+
end
|
25
|
+
|
26
|
+
if options[:exclusive_minimum] && super_data <= options[:exclusive_minimum]
|
27
|
+
result.error "Value must have an exclusive minimum of #{options[:exclusive_minimum]}."
|
28
|
+
end
|
29
|
+
|
30
|
+
# Validate maximum #
|
31
|
+
if options[:maximum] && super_data > options[:maximum]
|
32
|
+
result.error "Value must have a maximum of #{options[:maximum]}."
|
33
|
+
end
|
34
|
+
|
35
|
+
if options[:exclusive_maximum] && super_data >= options[:exclusive_maximum]
|
36
|
+
result.error "Value must have an exclusive maximum of #{options[:exclusive_maximum]}."
|
37
|
+
end
|
38
|
+
|
39
|
+
# Validate multiple of #
|
40
|
+
if options[:multiple_of] && !compare_float((super_data % options[:multiple_of]), 0.0)
|
41
|
+
result.error "Value must be a multiple of #{options[:multiple_of]}."
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate_self
|
46
|
+
# Check that the options have the correct type
|
47
|
+
ATTRIBUTES.each do |attribute|
|
48
|
+
next if options[attribute].nil?
|
49
|
+
next unless allowed_types.keys.none? { |c| options[attribute].send(type_assertion_method, c) }
|
50
|
+
|
51
|
+
collection = allowed_types.values.map { |t| "\"#{t}\"" }.uniq.sort.join(' or ')
|
52
|
+
fail "Option \"#{attribute}\" must be a #{collection}"
|
53
|
+
end
|
54
|
+
|
55
|
+
if options[:minimum] && options[:maximum] && options[:minimum] > options[:maximum]
|
56
|
+
fail 'Option "minimum" can\'t be greater than "maximum".'
|
57
|
+
end
|
58
|
+
|
59
|
+
if options[:exclusive_minimum] && options[:exclusive_maximum]\
|
60
|
+
&& options[:exclusive_minimum] > options[:exclusive_maximum]
|
61
|
+
fail 'Option "exclusive_minimum" can\'t be greater than "exclusive_maximum".'
|
62
|
+
end
|
63
|
+
|
64
|
+
if options[:multiple_of]&.zero?
|
65
|
+
fail 'Option "multiple_of" can\'t be 0.'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def compare_float(first, second)
|
72
|
+
(first - second).abs < Float::EPSILON
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Schemacop
|
2
|
+
module V3
|
3
|
+
class ObjectNode < Node
|
4
|
+
def self.allowed_options
|
5
|
+
super + %i[classes strict]
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.create(classes, **options, &block)
|
9
|
+
options[:classes] = classes
|
10
|
+
super(**options, &block)
|
11
|
+
end
|
12
|
+
|
13
|
+
def as_json
|
14
|
+
{} # Not supported by Json Schema
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def allowed_types
|
20
|
+
Hash[@classes.map { |c| [c, c.name] }]
|
21
|
+
end
|
22
|
+
|
23
|
+
def init
|
24
|
+
@classes = Array(options.delete(:classes) || [])
|
25
|
+
@strict = options.delete(:strict)
|
26
|
+
@strict = true if @strict.nil?
|
27
|
+
end
|
28
|
+
|
29
|
+
def type_assertion_method
|
30
|
+
@strict ? :instance_of? : :is_a?
|
31
|
+
end
|
32
|
+
|
33
|
+
def validate_self
|
34
|
+
unless @strict.is_a?(TrueClass) || @strict.is_a?(FalseClass)
|
35
|
+
fail 'Option "strict" must be a "boolean".'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Schemacop
|
2
|
+
module V3
|
3
|
+
class OneOfNode < CombinationNode
|
4
|
+
def type
|
5
|
+
:oneOf
|
6
|
+
end
|
7
|
+
|
8
|
+
def _validate(data, result:)
|
9
|
+
super_data = super
|
10
|
+
return if super_data.nil?
|
11
|
+
|
12
|
+
matches = matches(super_data)
|
13
|
+
|
14
|
+
if matches.size == 1
|
15
|
+
matches.first._validate(super_data, result: result)
|
16
|
+
else
|
17
|
+
result.error "Matches #{matches.size} definitions but should match exactly 1."
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def validate_self
|
22
|
+
if @items.size < 2
|
23
|
+
fail 'Node "one_of" makes only sense with at least 2 items.'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Schemacop
|
2
|
+
module V3
|
3
|
+
class ReferenceNode < Node
|
4
|
+
def self.allowed_options
|
5
|
+
super + %i[path]
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.create(path, **options, &block)
|
9
|
+
options[:path] = path
|
10
|
+
super(**options, &block)
|
11
|
+
end
|
12
|
+
|
13
|
+
def as_json
|
14
|
+
process_json([], '$ref': "#/definitions/#{@path}")
|
15
|
+
end
|
16
|
+
|
17
|
+
def _validate(data, result:)
|
18
|
+
super_data = super
|
19
|
+
return if super_data.nil?
|
20
|
+
|
21
|
+
# Lookup schema #
|
22
|
+
node = target
|
23
|
+
fail "Schema #{@path.to_s.inspect} not found." unless node
|
24
|
+
|
25
|
+
# Validate schema #
|
26
|
+
node._validate(super_data, result: result)
|
27
|
+
end
|
28
|
+
|
29
|
+
def target
|
30
|
+
schemas[@path] || Schemacop.context.schemas[@path] || GlobalContext.schema_for(@path)
|
31
|
+
end
|
32
|
+
|
33
|
+
def cast(data)
|
34
|
+
data = default if data.nil?
|
35
|
+
return target.cast(data)
|
36
|
+
end
|
37
|
+
|
38
|
+
def used_external_schemas
|
39
|
+
schemas.include?(@path) ? [] : [@path]
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
def init
|
45
|
+
@path = options.delete(:path)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|