schemacop 2.4.7 → 3.0.0.rc0
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 +2 -1
- data/CHANGELOG.md +8 -0
- data/README.md +41 -708
- data/README_V2.md +775 -0
- data/README_V3.md +683 -0
- data/Rakefile +8 -12
- data/VERSION +1 -1
- data/lib/schemacop.rb +35 -37
- 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/{node_supporting_field.rb → v2/node_supporting_field.rb} +8 -10
- data/lib/schemacop/{node_supporting_type.rb → v2/node_supporting_type.rb} +6 -3
- 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 +219 -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 +217 -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 +214 -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 +199 -0
- data/test/unit/schemacop/v3/any_of_node_test.rb +218 -0
- data/test/unit/schemacop/v3/array_node_test.rb +805 -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 +775 -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/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 -118
- 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,142 @@
|
|
1
|
+
module Schemacop
|
2
|
+
module V2
|
3
|
+
class Node
|
4
|
+
attr_reader :options
|
5
|
+
|
6
|
+
class_attribute :allowed_options
|
7
|
+
self.allowed_options = {}.freeze
|
8
|
+
|
9
|
+
class_attribute :symbols
|
10
|
+
self.symbols = [].freeze
|
11
|
+
|
12
|
+
class_attribute :klasses
|
13
|
+
self.klasses = [].freeze
|
14
|
+
|
15
|
+
def self.option(key, default: nil)
|
16
|
+
self.allowed_options = allowed_options.merge(key => default)
|
17
|
+
end
|
18
|
+
|
19
|
+
option :if
|
20
|
+
option :check
|
21
|
+
option :cast
|
22
|
+
option :default
|
23
|
+
|
24
|
+
def type_label
|
25
|
+
str = (symbols.first || 'unknown').to_s
|
26
|
+
str += '*' if option?(:if)
|
27
|
+
return str
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.symbol(symbol)
|
31
|
+
self.symbols += [symbol]
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.clear_symbols
|
35
|
+
self.symbols = [].freeze
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.klass(klass)
|
39
|
+
self.klasses += [klass]
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.clear_klasses
|
43
|
+
self.klasses = [].freeze
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.register(symbols: [], klasses: [], clear: true, before: nil)
|
47
|
+
NodeResolver.register(self, before: before)
|
48
|
+
symbols = [*symbols]
|
49
|
+
klasses = [*klasses]
|
50
|
+
if clear
|
51
|
+
clear_symbols
|
52
|
+
clear_klasses
|
53
|
+
end
|
54
|
+
symbols.each { |s| symbol s }
|
55
|
+
klasses.each { |k| klass k }
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.type_matches?(type)
|
59
|
+
symbol_matches?(type) || class_matches?(type)
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.symbol_matches?(type)
|
63
|
+
return false unless type.is_a?(Symbol)
|
64
|
+
|
65
|
+
symbols.include?(type)
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.class_matches?(type)
|
69
|
+
return false unless type.is_a?(Class)
|
70
|
+
|
71
|
+
klasses.each do |klass|
|
72
|
+
return true if type <= klass
|
73
|
+
end
|
74
|
+
return false
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.build(options, &block)
|
78
|
+
new(options, &block)
|
79
|
+
end
|
80
|
+
|
81
|
+
def initialize(options = {})
|
82
|
+
# Check and save given options
|
83
|
+
@options = self.class.allowed_options.merge(options)
|
84
|
+
if (obsolete_opts = @options.keys - self.class.allowed_options.keys).any?
|
85
|
+
fail Exceptions::InvalidSchemaError,
|
86
|
+
"Unrecognized option(s) #{obsolete_opts.inspect} for #{self.class.inspect}, allowed options: #{self.class.allowed_options.keys.inspect}."
|
87
|
+
end
|
88
|
+
|
89
|
+
if option?(:cast) && self.class.klasses.size > 1
|
90
|
+
fail Exceptions::InvalidSchemaError,
|
91
|
+
"Casting is only allowed for single-value datatypes, but type #{self.class.inspect} has classes "\
|
92
|
+
"#{self.class.klasses.map(&:inspect)}."
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def option(key)
|
97
|
+
options[key]
|
98
|
+
end
|
99
|
+
|
100
|
+
def option?(key)
|
101
|
+
!!options[key]
|
102
|
+
end
|
103
|
+
|
104
|
+
def exec_block
|
105
|
+
fail Exceptions::InvalidSchemaError, 'Node does not support block.' if block_given?
|
106
|
+
end
|
107
|
+
|
108
|
+
def resolve_type_klass(type)
|
109
|
+
klass = NodeResolver.resolve(type)
|
110
|
+
unless klass
|
111
|
+
fail Exceptions::InvalidSchemaError, "No validation class found for type #{type.inspect}."
|
112
|
+
end
|
113
|
+
|
114
|
+
return klass
|
115
|
+
end
|
116
|
+
|
117
|
+
def validate(data, collector)
|
118
|
+
validate_custom_check(data, collector)
|
119
|
+
end
|
120
|
+
|
121
|
+
def type_matches?(data)
|
122
|
+
self.class.type_matches?(data.class) && type_filter_matches?(data)
|
123
|
+
end
|
124
|
+
|
125
|
+
def type_filter_matches?(data)
|
126
|
+
!option?(:if) || option(:if).call(data)
|
127
|
+
end
|
128
|
+
|
129
|
+
protected
|
130
|
+
|
131
|
+
def validate_custom_check(data, collector)
|
132
|
+
if option?(:check) && (check_result = option(:check).call(data)) != true
|
133
|
+
if check_result.is_a?(String)
|
134
|
+
collector.error "Custom :check failed: #{check_result}."
|
135
|
+
else
|
136
|
+
collector.error 'Custom :check failed.'
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module Schemacop
|
1
|
+
module Schemacop::V2
|
2
2
|
class NodeSupportingField < NodeWithBlock
|
3
3
|
block_method :req?
|
4
4
|
block_method :req!
|
@@ -23,7 +23,7 @@ module Schemacop
|
|
23
23
|
field(*args, required: true, allow_nil: false, &block)
|
24
24
|
end
|
25
25
|
|
26
|
-
|
26
|
+
alias req req!
|
27
27
|
|
28
28
|
def opt?(*args, &block)
|
29
29
|
field(*args, required: false, allow_nil: true, &block)
|
@@ -33,7 +33,7 @@ module Schemacop
|
|
33
33
|
field(*args, required: false, allow_nil: false, &block)
|
34
34
|
end
|
35
35
|
|
36
|
-
|
36
|
+
alias opt opt?
|
37
37
|
|
38
38
|
protected
|
39
39
|
|
@@ -42,14 +42,12 @@ module Schemacop
|
|
42
42
|
|
43
43
|
if @fields[name]
|
44
44
|
@fields[name].type(*args, &block)
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
type(*args, &block)
|
49
|
-
end
|
50
|
-
else
|
51
|
-
@fields[name] = FieldNode.new(name, required, &block)
|
45
|
+
elsif args.any?
|
46
|
+
@fields[name] = FieldNode.new(name, required) do
|
47
|
+
type(*args, &block)
|
52
48
|
end
|
49
|
+
else
|
50
|
+
@fields[name] = FieldNode.new(name, required, &block)
|
53
51
|
end
|
54
52
|
|
55
53
|
@fields[name].type(:nil) if allow_nil
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module Schemacop
|
1
|
+
module Schemacop::V2
|
2
2
|
class NodeSupportingType < NodeWithBlock
|
3
3
|
block_method :type
|
4
4
|
|
@@ -14,6 +14,7 @@ module Schemacop
|
|
14
14
|
|
15
15
|
if @types.none?
|
16
16
|
fail Exceptions::InvalidSchemaError, 'Block must contain a type definition or not be given at all.' if block_given?
|
17
|
+
|
17
18
|
type :object
|
18
19
|
end
|
19
20
|
|
@@ -46,8 +47,8 @@ module Schemacop
|
|
46
47
|
# happens in here directly and not in the constructor. This way we can
|
47
48
|
# always call 'type', even if we don't have one and the type is auto-guessed
|
48
49
|
# as it formerly was the case in the constructor.
|
49
|
-
def type(*args, &block)
|
50
|
-
options =
|
50
|
+
def type(*args, **kwargs, &block)
|
51
|
+
options = kwargs
|
51
52
|
types = [*args.shift]
|
52
53
|
subtypes = args
|
53
54
|
|
@@ -101,9 +102,11 @@ module Schemacop
|
|
101
102
|
def cast!(data, collector)
|
102
103
|
@types.each do |type|
|
103
104
|
next unless type.option?(:cast) && !type.type_matches?(data) && type.type_filter_matches?(data)
|
105
|
+
|
104
106
|
caster = Caster.new(type.option(:cast), data, type.class.klasses.first)
|
105
107
|
|
106
108
|
next unless caster.castable?
|
109
|
+
|
107
110
|
begin
|
108
111
|
data = caster.cast
|
109
112
|
collector.override_value(data)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module Schemacop
|
1
|
+
module Schemacop::V2
|
2
2
|
class NodeWithBlock < Node
|
3
3
|
class_attribute :block_methods
|
4
4
|
self.block_methods = [].freeze
|
@@ -9,7 +9,8 @@ module Schemacop
|
|
9
9
|
|
10
10
|
def exec_block(&block)
|
11
11
|
return unless block_given?
|
12
|
-
|
12
|
+
|
13
|
+
se = Schemacop::ScopedEnv.new(self, self.class.block_methods)
|
13
14
|
se.instance_exec(&block)
|
14
15
|
end
|
15
16
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Schemacop
|
2
|
+
module V2
|
3
|
+
class ArrayValidator < NodeSupportingType
|
4
|
+
register symbols: :array, klasses: Array
|
5
|
+
|
6
|
+
option :min # Minimal number of elements
|
7
|
+
option :max # Maximal number of elements
|
8
|
+
option :nil # Whether to allow nil values
|
9
|
+
|
10
|
+
def initialize(*args)
|
11
|
+
super
|
12
|
+
type(:nil) if option(:nil)
|
13
|
+
end
|
14
|
+
|
15
|
+
def validate(data, collector)
|
16
|
+
validate_custom_check(data, collector)
|
17
|
+
|
18
|
+
if option?(:min) && data.size < option(:min)
|
19
|
+
collector.error "Array must have more (>=) than #{option(:min)} elements."
|
20
|
+
end
|
21
|
+
if option?(:max) && data.size > option(:max)
|
22
|
+
collector.error "Array must have less (<=) than #{option(:max)} elements."
|
23
|
+
end
|
24
|
+
data.each_with_index do |entry, index|
|
25
|
+
collector.path("[#{index}]", index, :array) do
|
26
|
+
validate_types(entry, collector)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Schemacop
|
2
|
+
module V2
|
3
|
+
class HashValidator < NodeSupportingField
|
4
|
+
register symbols: :hash, klasses: Hash
|
5
|
+
|
6
|
+
option :allow_obsolete_keys
|
7
|
+
|
8
|
+
def validate(data, collector)
|
9
|
+
super
|
10
|
+
|
11
|
+
if data.is_a? ActiveSupport::HashWithIndifferentAccess
|
12
|
+
allowed_fields = @fields.keys.map { |k| k.is_a?(String) ? k.to_sym : k }
|
13
|
+
data_keys = data.keys.map { |k| k.is_a?(String) ? k.to_sym : k }
|
14
|
+
|
15
|
+
# If the same key is specified in the schema as string and symbol, we
|
16
|
+
# definitely expect a Ruby hash and not one with indifferent access
|
17
|
+
if @fields.keys.length != Set.new(allowed_fields).length
|
18
|
+
fail Exceptions::ValidationError, 'Hash expected, but got ActiveSupport::HashWithIndifferentAccess.'
|
19
|
+
end
|
20
|
+
else
|
21
|
+
allowed_fields = @fields.keys
|
22
|
+
data_keys = data.keys
|
23
|
+
end
|
24
|
+
|
25
|
+
obsolete_keys = data_keys - allowed_fields
|
26
|
+
|
27
|
+
if !option?(:allow_obsolete_keys) && obsolete_keys.any?
|
28
|
+
collector.error "Obsolete keys: #{obsolete_keys.inspect}."
|
29
|
+
end
|
30
|
+
|
31
|
+
@fields.each_value do |field|
|
32
|
+
field.validate(data, collector)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Schemacop
|
2
|
+
module V2
|
3
|
+
class NumberValidator < Node
|
4
|
+
register symbols: :number, klasses: [Integer, Float]
|
5
|
+
|
6
|
+
option :min
|
7
|
+
option :max
|
8
|
+
|
9
|
+
def validate(data, collector)
|
10
|
+
super
|
11
|
+
|
12
|
+
if option?(:min) && data < option(:min)
|
13
|
+
collector.error "Value must be >= #{option(:min)}."
|
14
|
+
end
|
15
|
+
if option?(:max) && data > option(:max)
|
16
|
+
collector.error "Value must be <= #{option(:max)}."
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Schemacop
|
2
|
+
module V2
|
3
|
+
class ObjectValidator < Node
|
4
|
+
register symbols: :object, klasses: BasicObject
|
5
|
+
|
6
|
+
option :classes
|
7
|
+
option :strict
|
8
|
+
|
9
|
+
def type_label
|
10
|
+
"#{super} (#{classes.join(', ')})"
|
11
|
+
end
|
12
|
+
|
13
|
+
def type_matches?(data)
|
14
|
+
if option(:strict).is_a?(FalseClass)
|
15
|
+
sub_or_class = classes.map { |klass| data.class <= klass }.include?(true)
|
16
|
+
super && (classes.empty? || sub_or_class) && !data.nil?
|
17
|
+
else
|
18
|
+
super && (classes.empty? || classes.include?(data.class)) && !data.nil?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def classes
|
25
|
+
[*option(:classes)]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Schemacop
|
2
|
+
module V2
|
3
|
+
class StringValidator < Node
|
4
|
+
register symbols: :string, klasses: String
|
5
|
+
|
6
|
+
option :min
|
7
|
+
option :max
|
8
|
+
|
9
|
+
def initialize(options = {})
|
10
|
+
super(options)
|
11
|
+
|
12
|
+
validate_options!
|
13
|
+
end
|
14
|
+
|
15
|
+
def validate(data, collector)
|
16
|
+
super
|
17
|
+
|
18
|
+
if option?(:min) && data.size < option(:min)
|
19
|
+
collector.error "String must be longer (>=) than #{option(:min)} characters."
|
20
|
+
end
|
21
|
+
if option?(:max) && data.size > option(:max)
|
22
|
+
collector.error "String must be shorter (<=) than #{option(:max)} characters."
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def validate_options!
|
29
|
+
option_schema = Schema.new :integer, min: 0
|
30
|
+
|
31
|
+
if option?(:min) && option_schema.invalid?(option(:min))
|
32
|
+
fail Exceptions::InvalidSchemaError, 'String option :min must be an integer >= 0.'
|
33
|
+
elsif option?(:max) && option_schema.invalid?(option(:max))
|
34
|
+
fail Exceptions::InvalidSchemaError, 'String option :max must be an integer >= 0.'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|