schemacop 3.0.14 → 3.0.17
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/.github/workflows/ruby.yml +1 -1
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +20 -0
- data/LICENSE +1 -1
- data/README.md +4 -3
- data/README_V3.md +109 -1
- data/Rakefile +3 -3
- data/VERSION +1 -1
- data/lib/schemacop/v2/collector.rb +1 -1
- data/lib/schemacop/v3/array_node.rb +32 -3
- data/lib/schemacop/v3/global_context.rb +1 -1
- data/lib/schemacop/v3/hash_node.rb +2 -2
- data/lib/schemacop/v3/node.rb +5 -3
- data/lib/schemacop/v3/object_node.rb +1 -1
- data/lib/schemacop/v3/string_node.rb +6 -35
- data/lib/schemacop/v3.rb +1 -1
- data/lib/schemacop.rb +77 -0
- data/schemacop.gemspec +6 -6
- data/test/unit/schemacop/v2/nil_dis_allow_test.rb +1 -1
- data/test/unit/schemacop/v2/validator_symbol_test.rb +1 -1
- data/test/unit/schemacop/v3/array_node_test.rb +106 -0
- data/test/unit/schemacop/v3/boolean_node_test.rb +1 -1
- data/test/unit/schemacop/v3/global_context_test.rb +9 -9
- data/test/unit/schemacop/v3/integer_node_test.rb +5 -0
- data/test/unit/schemacop/v3/node_test.rb +8 -0
- data/test/unit/schemacop/v3/number_node_test.rb +5 -0
- data/test/unit/schemacop/v3/string_node_test.rb +73 -27
- data/test/unit/schemacop/v3/symbol_node_test.rb +2 -2
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c486c27262569e4a3f3f3b9751aedfab72a15611c457c9748577e2d2625f43ec
|
4
|
+
data.tar.gz: dc61cc778afc5403904fcc51cb74c81fadb0d5b3142ffb91f0b09b2eb82f4c69
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2ad16e54c5d883e62b456718dbb8e086c6e0cad805b88996817876176451fe04b0ababa4410762e2d58adbefbdce34e69a8a0f0ff9499b683dbdfcb3b89185f9
|
7
|
+
data.tar.gz: b08189742b46257f92dd7e54fd0f917cbb03b95092add3557a90b428f64fdc7ad7428ae96004ee5a645eefec83b70934b3a03f39152fa71d35dc4132bfa9694b
|
data/.github/workflows/ruby.yml
CHANGED
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
+
## 3.0.17 (2022-06-08)
|
4
|
+
|
5
|
+
* Add options `filter` and `reject` to array nodes which allow to filter arrays
|
6
|
+
before they are validated.
|
7
|
+
|
8
|
+
* `#64545`: Fix an issue where `cast_str` in conjunction with `number` notes
|
9
|
+
lead to parsing errors when the given number had a leading zero, e.g. parsing
|
10
|
+
the string `08` lead to an error, as the number was interpreted as an octal
|
11
|
+
string. Numbers are now always being treated as decimal with base 10.
|
12
|
+
|
13
|
+
## 3.0.16 (2021-11-23)
|
14
|
+
|
15
|
+
* Add setting `Schemacop.v3_default_options` which allows to set default node
|
16
|
+
options vor V3 schemas. This is particularly useful for the option `cast_str`
|
17
|
+
to allow string casting globally.
|
18
|
+
|
19
|
+
## 3.0.15 (2021-10-11)
|
20
|
+
|
21
|
+
* Add support for custom string formatters
|
22
|
+
|
3
23
|
## 3.0.14 (2021-10-11)
|
4
24
|
|
5
25
|
* Add string format `integer_list`
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -14,9 +14,10 @@ Schemacop is tested with the following ruby versions:
|
|
14
14
|
|
15
15
|
* 2.6.2
|
16
16
|
* 2.7.1
|
17
|
-
* 3.0.
|
17
|
+
* 3.0.1
|
18
|
+
* 3.1.0
|
18
19
|
|
19
|
-
Other ruby versions might work but are not covered by our
|
20
|
+
Other ruby versions might work but are not covered by our automated tests.
|
20
21
|
|
21
22
|
## Basic example
|
22
23
|
|
@@ -118,4 +119,4 @@ To run tests:
|
|
118
119
|
|
119
120
|
## Copyright
|
120
121
|
|
121
|
-
Copyright © 2016 -
|
122
|
+
Copyright © 2016 - 2022 Sitrox. See `LICENSE` for further details.
|
data/README_V3.md
CHANGED
@@ -21,6 +21,7 @@
|
|
21
21
|
13. [Reference](#reference)
|
22
22
|
5. [Context](#context)
|
23
23
|
6. [External schemas](#external-schemas)
|
24
|
+
7. [Default options](#default-options)
|
24
25
|
|
25
26
|
## Validation
|
26
27
|
|
@@ -252,6 +253,24 @@ transformed into various types.
|
|
252
253
|
* `symbol`
|
253
254
|
The string can be anything and will be casted to a ruby `Symbol` object.
|
254
255
|
|
256
|
+
#### Custom Formats
|
257
|
+
|
258
|
+
You can also implement your custom formats or override the behavior of the
|
259
|
+
standard formats. This can be done in the initializer configuration (in case of
|
260
|
+
a Rails appliation):
|
261
|
+
|
262
|
+
```ruby
|
263
|
+
# config/initializers/schemacop.rb
|
264
|
+
Schemacop.register_string_formatter(
|
265
|
+
:character_array, # Formatter name
|
266
|
+
pattern: /^[a-zA-Z](,[a-zA-Z])*/, # Regex pattern for validation
|
267
|
+
handler: ->(value) { value.split(',') } # Casting callback
|
268
|
+
)
|
269
|
+
|
270
|
+
# In your schema
|
271
|
+
str! :my_list, format: :character_array
|
272
|
+
```
|
273
|
+
|
255
274
|
#### Examples
|
256
275
|
|
257
276
|
```ruby
|
@@ -321,6 +340,8 @@ integer can be done.
|
|
321
340
|
When set to `true`, this node also accepts strings that can be casted to an integer, e.g.
|
322
341
|
the values `'-5'` or `'42'`. Please note that you can only validate numbers which
|
323
342
|
are in the `Integer` format. Blank strings will be treated equally as `nil`.
|
343
|
+
Strings will be parsed with base 10, so only decimal numbers are allowed.
|
344
|
+
Leading zeroes will be ignored.
|
324
345
|
|
325
346
|
#### Examples
|
326
347
|
|
@@ -402,7 +423,9 @@ With the various available options, validations on the value of the number can b
|
|
402
423
|
When set to `true`, this node also accepts strings that can be casted to a number, e.g.
|
403
424
|
the values `'0.1'` or `'3.1415'`. Please note that you can only validate numbers which
|
404
425
|
are in the `Integer` or `Float` format, i.e. values like `'1.5r'` or `'(4 + 0i)'` will
|
405
|
-
not work. Blank strings will be treated equally as `nil`.
|
426
|
+
not work. Blank strings will be treated equally as `nil`. Strings will be
|
427
|
+
parsed with base 10, so only decimal numbers are allowed. Leading zeroes will
|
428
|
+
be ignored.
|
406
429
|
|
407
430
|
#### Examples
|
408
431
|
|
@@ -572,6 +595,26 @@ It consists of one or multiple values, which can be validated using arbitrary no
|
|
572
595
|
each other, or if there may be duplicate values. By default, this is false,
|
573
596
|
i.e. duplicate values are allowed
|
574
597
|
|
598
|
+
* `filter`
|
599
|
+
This option allows you to filter an array *before it is validated*. When using
|
600
|
+
casting, this also filters the data returned by the validator. If the given value
|
601
|
+
is a `Symbol`, the method with the given name will be executed on each array
|
602
|
+
item in order to determine whether it is kept. If the given value is a `Proc`,
|
603
|
+
it will be called for each array item to determine whether it is kept. Both
|
604
|
+
functions or Procs are expected to return either `true` or `false`.
|
605
|
+
|
606
|
+
This is the inverse of option `reject`.
|
607
|
+
|
608
|
+
* `reject`
|
609
|
+
This option allows you to filter an array *before it is validated*. When using
|
610
|
+
casting, this also filters the data returned by the validator. If the given value
|
611
|
+
is a `Symbol`, the method with the given name will be executed on each array
|
612
|
+
item in order to determine whether it is removed. If the given value is a `Proc`,
|
613
|
+
it will be called for each array item to determine whether it is removed. Both
|
614
|
+
functions or Procs are expected to return either `true` or `false`.
|
615
|
+
|
616
|
+
This is the inverse of option `filter`.
|
617
|
+
|
575
618
|
#### Contains
|
576
619
|
|
577
620
|
The `array` node features the *contains* node, which you can use with the DSL
|
@@ -747,6 +790,53 @@ schema.validate!([1, 'foo']) # => [1, "foo"]
|
|
747
790
|
schema.validate!([1, :bar]) # => Schemacop::Exceptions::ValidationError: /[1]: Matches 0 definitions but should match exactly 1.
|
748
791
|
```
|
749
792
|
|
793
|
+
#### Filtering
|
794
|
+
|
795
|
+
Using the options `filter` and `reject`, arrays can be filtered. Filtering
|
796
|
+
happens before validation. Both options behave in the same way, with the only
|
797
|
+
difference being that `filter` uses a inclusive approach and `reject` an
|
798
|
+
exclusive (see [filter](https://apidock.com/ruby/Array/filter) and
|
799
|
+
[reject](https://apidock.com/ruby/Array/reject] in the Ruby API, as they behave
|
800
|
+
in a similar manor).
|
801
|
+
|
802
|
+
You can either pass a Symbol which specifies the name of the method that is
|
803
|
+
called on each array item:
|
804
|
+
|
805
|
+
```ruby
|
806
|
+
# FYI: This example requires active_support for the blank? method
|
807
|
+
schema = Schemacop::Schema3.new :array, reject: :blank? do
|
808
|
+
list :string
|
809
|
+
end
|
810
|
+
|
811
|
+
schema.validate!(['', 'foo']) # => ["foo"]
|
812
|
+
```
|
813
|
+
|
814
|
+
You can also pass a proc to `filter` or `reject`:
|
815
|
+
|
816
|
+
```ruby
|
817
|
+
schema = Schemacop::Schema3.new :array, filter: ->(value) { value.is_a?(String) } do
|
818
|
+
list :string
|
819
|
+
end
|
820
|
+
|
821
|
+
schema.validate!(['foo', 42]) # => ["foo"]
|
822
|
+
```
|
823
|
+
|
824
|
+
Note that the given method name or proc should work with all element types that
|
825
|
+
could possibly be in the (unvalidated) array. If a `NoMethodError` is
|
826
|
+
encountered during a single filtering iteration, the element will be left in the
|
827
|
+
array and, in most cases, trigger a validation error later:
|
828
|
+
|
829
|
+
```ruby
|
830
|
+
schema = Schemacop::Schema3.new :array, reject: :zero? do
|
831
|
+
list :integer
|
832
|
+
end
|
833
|
+
|
834
|
+
# In this example, the value 'foo' does not respond to the method `zero?` which
|
835
|
+
# lead to a `NoMethodError` that is caught by Schemacop which in turn leaves the
|
836
|
+
# value in the array.
|
837
|
+
schema.validate!(['foo', 42, 0]) # => Schemacop::Exceptions::ValidationError: /[0]: Invalid type, got type "String", expected "integer".
|
838
|
+
```
|
839
|
+
|
750
840
|
### Hash
|
751
841
|
|
752
842
|
Type: `:hash`\
|
@@ -1431,3 +1521,21 @@ Schemacop::V3::GlobalContext.eager_load!
|
|
1431
1521
|
As mentioned before, you can also use the external schemas without having to
|
1432
1522
|
eager-load them, but if you use the schemas multiple times, it might be better
|
1433
1523
|
to eager-load them on start of your application / script.
|
1524
|
+
|
1525
|
+
## Default options
|
1526
|
+
|
1527
|
+
Using the setting `Schemacop.v3_default_options`, you can specify a hash
|
1528
|
+
containing default options that will be used for every schemacop node (options
|
1529
|
+
not supported by a particular node are automatically ignored). Options passed
|
1530
|
+
directly to a node still take precedence. The setting can be set in an
|
1531
|
+
initializer:
|
1532
|
+
|
1533
|
+
```ruby
|
1534
|
+
# config/initializers/schemacop.rb
|
1535
|
+
Schemacop.v3_default_options = { cast_str: true }.freeze
|
1536
|
+
|
1537
|
+
# Example schema: As cast_str is enabled in the default options, strings will
|
1538
|
+
# automatically be casted where supported.
|
1539
|
+
schema = Schemacop::Schema3.new(:integer)
|
1540
|
+
schema.validate!('42') # => 42
|
1541
|
+
```
|
data/Rakefile
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
task :gemspec do
|
2
2
|
gemspec = Gem::Specification.new do |spec|
|
3
3
|
spec.name = 'schemacop'
|
4
|
-
spec.version =
|
4
|
+
spec.version = File.read('VERSION').chomp
|
5
5
|
spec.authors = ['Sitrox']
|
6
6
|
spec.summary = %(
|
7
7
|
Schemacop validates ruby structures consisting of nested hashes and arrays
|
@@ -24,13 +24,13 @@ task :gemspec do
|
|
24
24
|
spec.add_development_dependency 'minitest'
|
25
25
|
spec.add_development_dependency 'minitest-reporters'
|
26
26
|
spec.add_development_dependency 'colorize'
|
27
|
-
spec.add_development_dependency 'rubocop', '
|
27
|
+
spec.add_development_dependency 'rubocop', '1.24.1'
|
28
28
|
spec.add_development_dependency 'pry'
|
29
29
|
spec.add_development_dependency 'byebug'
|
30
30
|
spec.add_development_dependency 'simplecov', '0.21.2'
|
31
31
|
end
|
32
32
|
|
33
|
-
File.
|
33
|
+
File.write('schemacop.gemspec', gemspec.to_ruby.strip)
|
34
34
|
end
|
35
35
|
|
36
36
|
begin
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.0.
|
1
|
+
3.0.17
|
@@ -60,7 +60,7 @@ module Schemacop::V2
|
|
60
60
|
def exception_message
|
61
61
|
# rubocop:disable Style/StringConcatenation
|
62
62
|
return "Schemacop validation failed:\n" + @exceptions.map do |e|
|
63
|
-
"- #{e[:path].join
|
63
|
+
"- #{e[:path].join}: #{e[:message]}"
|
64
64
|
end.join("\n")
|
65
65
|
# rubocop:enable Style/StringConcatenation
|
66
66
|
end
|
@@ -10,7 +10,7 @@ module Schemacop
|
|
10
10
|
supports_children
|
11
11
|
|
12
12
|
def self.allowed_options
|
13
|
-
super + ATTRIBUTES + %i[additional_items]
|
13
|
+
super + ATTRIBUTES + %i[additional_items reject filter]
|
14
14
|
end
|
15
15
|
|
16
16
|
def self.dsl_methods
|
@@ -80,7 +80,10 @@ module Schemacop
|
|
80
80
|
super_data = super
|
81
81
|
return if super_data.nil?
|
82
82
|
|
83
|
-
#
|
83
|
+
# Preprocess
|
84
|
+
super_data = preprocess_array(super_data)
|
85
|
+
|
86
|
+
# Validate length
|
84
87
|
length = super_data.size
|
85
88
|
|
86
89
|
if options[:min_items] && length < options[:min_items]
|
@@ -163,11 +166,37 @@ module Schemacop
|
|
163
166
|
end
|
164
167
|
end
|
165
168
|
|
166
|
-
return result
|
169
|
+
return preprocess_array(result)
|
167
170
|
end
|
168
171
|
|
169
172
|
protected
|
170
173
|
|
174
|
+
def preprocess_array(value)
|
175
|
+
# Handle filter
|
176
|
+
if options[:filter]
|
177
|
+
block = Proc.new(&options[:filter])
|
178
|
+
|
179
|
+
value = value.filter do |item|
|
180
|
+
block.call(item)
|
181
|
+
rescue NoMethodError
|
182
|
+
true
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
# Handle reject
|
187
|
+
if options[:reject]
|
188
|
+
block = Proc.new(&options[:reject])
|
189
|
+
|
190
|
+
value = value.reject do |item|
|
191
|
+
block.call(item)
|
192
|
+
rescue NoMethodError
|
193
|
+
false
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
return value
|
198
|
+
end
|
199
|
+
|
171
200
|
def list?
|
172
201
|
list_item.present?
|
173
202
|
end
|
@@ -86,7 +86,7 @@ module Schemacop
|
|
86
86
|
begin
|
87
87
|
@current_schemas = []
|
88
88
|
env = ScopedEnv.new(self, DSL_METHODS)
|
89
|
-
env.instance_eval
|
89
|
+
env.instance_eval File.read(path)
|
90
90
|
rescue StandardError => e
|
91
91
|
fail "Could not load schema #{path.inspect}: #{e.message}"
|
92
92
|
end
|
@@ -55,8 +55,8 @@ module Schemacop
|
|
55
55
|
end
|
56
56
|
|
57
57
|
json = {}
|
58
|
-
json[:properties] =
|
59
|
-
json[:patternProperties] =
|
58
|
+
json[:properties] = properties.values.map { |p| [p.name, p.as_json] }.to_h if properties.any?
|
59
|
+
json[:patternProperties] = pattern_properties.values.map { |p| [V3.sanitize_exp(p.name), p.as_json] }.to_h if pattern_properties.any?
|
60
60
|
|
61
61
|
# In schemacop, by default, additional properties are not allowed,
|
62
62
|
# the users explicitly need to enable additional properties
|
data/lib/schemacop/v3/node.rb
CHANGED
@@ -30,6 +30,8 @@ module Schemacop
|
|
30
30
|
|
31
31
|
node = klass.new(**options, &block)
|
32
32
|
|
33
|
+
options = Schemacop.v3_default_options.slice(*klass.allowed_options).merge(options)
|
34
|
+
|
33
35
|
if options.delete(:cast_str)
|
34
36
|
format = NodeRegistry.name(klass)
|
35
37
|
one_of_options = {
|
@@ -197,10 +199,10 @@ module Schemacop
|
|
197
199
|
|
198
200
|
# Apply default #
|
199
201
|
if data.nil?
|
200
|
-
if
|
201
|
-
data = default
|
202
|
-
else
|
202
|
+
if default.nil?
|
203
203
|
return nil
|
204
|
+
else
|
205
|
+
data = default
|
204
206
|
end
|
205
207
|
end
|
206
208
|
|
@@ -7,21 +7,6 @@ module Schemacop
|
|
7
7
|
format
|
8
8
|
].freeze
|
9
9
|
|
10
|
-
# rubocop:disable Layout/LineLength
|
11
|
-
FORMAT_PATTERNS = {
|
12
|
-
date: /^([0-9]{4})-?(1[0-2]|0[1-9])-?(3[01]|0[1-9]|[12][0-9])$/,
|
13
|
-
'date-time': /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?(Z|[+-](?:2[0-3]|[01][0-9]):[0-5][0-9])?$/,
|
14
|
-
time: /^(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?(Z|[+-](?:2[0-3]|[01][0-9]):[0-5][0-9])?$/,
|
15
|
-
email: URI::MailTo::EMAIL_REGEXP,
|
16
|
-
boolean: /^(true|false|0|1)$/,
|
17
|
-
binary: nil,
|
18
|
-
symbol: nil,
|
19
|
-
integer: /^-?[0-9]+$/,
|
20
|
-
number: /^-?[0-9]+(\.[0-9]+)?$/,
|
21
|
-
'integer-list': /^(-?[0-9]+)(,-?[0-9]+)*$/
|
22
|
-
}.freeze
|
23
|
-
# rubocop:enable Layout/LineLength
|
24
|
-
|
25
10
|
def self.allowed_options
|
26
11
|
super + ATTRIBUTES + %i[format_options pattern allow_blank]
|
27
12
|
end
|
@@ -71,8 +56,9 @@ module Schemacop
|
|
71
56
|
end
|
72
57
|
|
73
58
|
# Validate format #
|
74
|
-
if options[:format] &&
|
75
|
-
pattern =
|
59
|
+
if options[:format] && Schemacop.string_formatters.include?(options[:format])
|
60
|
+
pattern = Schemacop.string_formatters[options[:format]][:pattern]
|
61
|
+
|
76
62
|
if pattern && !super_data.match?(pattern)
|
77
63
|
result.error "String does not match format #{options[:format].to_s.inspect}."
|
78
64
|
elsif options[:format_options] && Node.resolve_class(options[:format])
|
@@ -91,23 +77,8 @@ module Schemacop
|
|
91
77
|
return nil
|
92
78
|
end
|
93
79
|
|
94
|
-
|
95
|
-
|
96
|
-
%w[true 1].include?(to_cast)
|
97
|
-
when :date
|
98
|
-
return Date.parse(to_cast)
|
99
|
-
when :'date-time'
|
100
|
-
return DateTime.parse(to_cast)
|
101
|
-
when :time
|
102
|
-
Time.parse(to_cast)
|
103
|
-
when :integer
|
104
|
-
return Integer(to_cast)
|
105
|
-
when :number
|
106
|
-
return Float(to_cast)
|
107
|
-
when :'integer-list'
|
108
|
-
return to_cast.split(',').map(&:to_i)
|
109
|
-
when :symbol
|
110
|
-
return to_cast.to_sym
|
80
|
+
if (handler = Schemacop.string_formatters.dig(options[:format], :handler))
|
81
|
+
return handler.call(to_cast)
|
111
82
|
else
|
112
83
|
return to_cast
|
113
84
|
end
|
@@ -122,7 +93,7 @@ module Schemacop
|
|
122
93
|
end
|
123
94
|
|
124
95
|
def validate_self
|
125
|
-
if options.include?(:format) && !
|
96
|
+
if options.include?(:format) && !Schemacop.string_formatters.include?(options[:format])
|
126
97
|
fail "Format #{options[:format].to_s.inspect} is not supported."
|
127
98
|
end
|
128
99
|
|
data/lib/schemacop/v3.rb
CHANGED
@@ -9,7 +9,7 @@ module Schemacop
|
|
9
9
|
return exp if exp.is_a?(String)
|
10
10
|
|
11
11
|
_start_slash, caret, exp, dollar, _end_slash, flags = exp.inspect.match(%r{^(/?)(\^)?(.*?)(\$)?(/?)([ixm]*)?$}).captures
|
12
|
-
flags = flags.
|
12
|
+
flags = flags.chars
|
13
13
|
|
14
14
|
if flags.delete('i')
|
15
15
|
exp = "(?i)(#{exp})"
|
data/lib/schemacop.rb
CHANGED
@@ -13,6 +13,83 @@ module Schemacop
|
|
13
13
|
mattr_accessor :default_schema_version
|
14
14
|
self.default_schema_version = 3
|
15
15
|
|
16
|
+
mattr_accessor :string_formatters
|
17
|
+
self.string_formatters = {}
|
18
|
+
|
19
|
+
mattr_accessor :v3_default_options
|
20
|
+
self.v3_default_options = {}
|
21
|
+
|
22
|
+
def self.register_string_formatter(name, pattern:, handler:)
|
23
|
+
name = name.to_s.dasherize.to_sym
|
24
|
+
|
25
|
+
string_formatters[name] = {
|
26
|
+
pattern: pattern,
|
27
|
+
handler: handler
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
register_string_formatter(
|
32
|
+
:date,
|
33
|
+
pattern: /^([0-9]{4})-?(1[0-2]|0[1-9])-?(3[01]|0[1-9]|[12][0-9])$/,
|
34
|
+
handler: ->(value) { Date.parse(value) }
|
35
|
+
)
|
36
|
+
|
37
|
+
# rubocop: disable Layout/LineLength
|
38
|
+
register_string_formatter(
|
39
|
+
:'date-time',
|
40
|
+
pattern: /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?(Z|[+-](?:2[0-3]|[01][0-9]):[0-5][0-9])?$/,
|
41
|
+
handler: ->(value) { DateTime.parse(value) }
|
42
|
+
)
|
43
|
+
# rubocop: enable Layout/LineLength
|
44
|
+
|
45
|
+
register_string_formatter(
|
46
|
+
:time,
|
47
|
+
pattern: /^(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?(Z|[+-](?:2[0-3]|[01][0-9]):[0-5][0-9])?$/,
|
48
|
+
handler: ->(value) { Time.parse(value) }
|
49
|
+
)
|
50
|
+
|
51
|
+
register_string_formatter(
|
52
|
+
:email,
|
53
|
+
pattern: URI::MailTo::EMAIL_REGEXP,
|
54
|
+
handler: ->(value) { value }
|
55
|
+
)
|
56
|
+
|
57
|
+
register_string_formatter(
|
58
|
+
:boolean,
|
59
|
+
pattern: /^(true|false|0|1)$/,
|
60
|
+
handler: ->(value) { %w[true 1].include?(value) }
|
61
|
+
)
|
62
|
+
|
63
|
+
register_string_formatter(
|
64
|
+
:binary,
|
65
|
+
pattern: nil,
|
66
|
+
handler: ->(value) { value }
|
67
|
+
)
|
68
|
+
|
69
|
+
register_string_formatter(
|
70
|
+
:symbol,
|
71
|
+
pattern: nil,
|
72
|
+
handler: ->(value) { value.to_sym }
|
73
|
+
)
|
74
|
+
|
75
|
+
register_string_formatter(
|
76
|
+
:integer,
|
77
|
+
pattern: /^-?[0-9]+$/,
|
78
|
+
handler: ->(value) { Integer(value, 10) }
|
79
|
+
)
|
80
|
+
|
81
|
+
register_string_formatter(
|
82
|
+
:number,
|
83
|
+
pattern: /^-?[0-9]+(\.[0-9]+)?$/,
|
84
|
+
handler: ->(value) { Float(value) }
|
85
|
+
)
|
86
|
+
|
87
|
+
register_string_formatter(
|
88
|
+
:'integer-list',
|
89
|
+
pattern: /^(-?[0-9]+)(,-?[0-9]+)*$/,
|
90
|
+
handler: ->(value) { value.split(',').map { |i| Integer(i, 10) } }
|
91
|
+
)
|
92
|
+
|
16
93
|
def self.with_context(context)
|
17
94
|
prev_context = Thread.current[CONTEXT_THREAD_KEY]
|
18
95
|
Thread.current[CONTEXT_THREAD_KEY] = context
|
data/schemacop.gemspec
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
# stub: schemacop 3.0.
|
2
|
+
# stub: schemacop 3.0.17 ruby lib
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "schemacop".freeze
|
6
|
-
s.version = "3.0.
|
6
|
+
s.version = "3.0.17"
|
7
7
|
|
8
8
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
9
9
|
s.require_paths = ["lib".freeze]
|
10
10
|
s.authors = ["Sitrox".freeze]
|
11
|
-
s.date = "
|
11
|
+
s.date = "2022-06-08"
|
12
12
|
s.files = [".github/workflows/ruby.yml".freeze, ".gitignore".freeze, ".releaser_config".freeze, ".rubocop.yml".freeze, ".yardopts".freeze, "CHANGELOG.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "README_V2.md".freeze, "README_V3.md".freeze, "RUBY_VERSION".freeze, "Rakefile".freeze, "VERSION".freeze, "lib/schemacop.rb".freeze, "lib/schemacop/base_schema.rb".freeze, "lib/schemacop/exceptions.rb".freeze, "lib/schemacop/railtie.rb".freeze, "lib/schemacop/schema.rb".freeze, "lib/schemacop/schema2.rb".freeze, "lib/schemacop/schema3.rb".freeze, "lib/schemacop/scoped_env.rb".freeze, "lib/schemacop/v2.rb".freeze, "lib/schemacop/v2/caster.rb".freeze, "lib/schemacop/v2/collector.rb".freeze, "lib/schemacop/v2/dupper.rb".freeze, "lib/schemacop/v2/field_node.rb".freeze, "lib/schemacop/v2/node.rb".freeze, "lib/schemacop/v2/node_resolver.rb".freeze, "lib/schemacop/v2/node_supporting_field.rb".freeze, "lib/schemacop/v2/node_supporting_type.rb".freeze, "lib/schemacop/v2/node_with_block.rb".freeze, "lib/schemacop/v2/validator/array_validator.rb".freeze, "lib/schemacop/v2/validator/boolean_validator.rb".freeze, "lib/schemacop/v2/validator/float_validator.rb".freeze, "lib/schemacop/v2/validator/hash_validator.rb".freeze, "lib/schemacop/v2/validator/integer_validator.rb".freeze, "lib/schemacop/v2/validator/nil_validator.rb".freeze, "lib/schemacop/v2/validator/number_validator.rb".freeze, "lib/schemacop/v2/validator/object_validator.rb".freeze, "lib/schemacop/v2/validator/string_validator.rb".freeze, "lib/schemacop/v2/validator/symbol_validator.rb".freeze, "lib/schemacop/v3.rb".freeze, "lib/schemacop/v3/all_of_node.rb".freeze, "lib/schemacop/v3/any_of_node.rb".freeze, "lib/schemacop/v3/array_node.rb".freeze, "lib/schemacop/v3/boolean_node.rb".freeze, "lib/schemacop/v3/combination_node.rb".freeze, "lib/schemacop/v3/context.rb".freeze, "lib/schemacop/v3/dsl_scope.rb".freeze, "lib/schemacop/v3/global_context.rb".freeze, "lib/schemacop/v3/hash_node.rb".freeze, "lib/schemacop/v3/integer_node.rb".freeze, "lib/schemacop/v3/is_not_node.rb".freeze, "lib/schemacop/v3/node.rb".freeze, "lib/schemacop/v3/node_registry.rb".freeze, "lib/schemacop/v3/number_node.rb".freeze, "lib/schemacop/v3/numeric_node.rb".freeze, "lib/schemacop/v3/object_node.rb".freeze, "lib/schemacop/v3/one_of_node.rb".freeze, "lib/schemacop/v3/reference_node.rb".freeze, "lib/schemacop/v3/result.rb".freeze, "lib/schemacop/v3/string_node.rb".freeze, "lib/schemacop/v3/symbol_node.rb".freeze, "schemacop.gemspec".freeze, "test/lib/test_helper.rb".freeze, "test/schemas/nested/group.rb".freeze, "test/schemas/user.rb".freeze, "test/unit/schemacop/v2/casting_test.rb".freeze, "test/unit/schemacop/v2/collector_test.rb".freeze, "test/unit/schemacop/v2/custom_check_test.rb".freeze, "test/unit/schemacop/v2/custom_if_test.rb".freeze, "test/unit/schemacop/v2/defaults_test.rb".freeze, "test/unit/schemacop/v2/empty_test.rb".freeze, "test/unit/schemacop/v2/nil_dis_allow_test.rb".freeze, "test/unit/schemacop/v2/node_resolver_test.rb".freeze, "test/unit/schemacop/v2/short_forms_test.rb".freeze, "test/unit/schemacop/v2/types_test.rb".freeze, "test/unit/schemacop/v2/validator_array_test.rb".freeze, "test/unit/schemacop/v2/validator_boolean_test.rb".freeze, "test/unit/schemacop/v2/validator_float_test.rb".freeze, "test/unit/schemacop/v2/validator_hash_test.rb".freeze, "test/unit/schemacop/v2/validator_integer_test.rb".freeze, "test/unit/schemacop/v2/validator_nil_test.rb".freeze, "test/unit/schemacop/v2/validator_number_test.rb".freeze, "test/unit/schemacop/v2/validator_object_test.rb".freeze, "test/unit/schemacop/v2/validator_string_test.rb".freeze, "test/unit/schemacop/v2/validator_symbol_test.rb".freeze, "test/unit/schemacop/v3/all_of_node_test.rb".freeze, "test/unit/schemacop/v3/any_of_node_test.rb".freeze, "test/unit/schemacop/v3/array_node_test.rb".freeze, "test/unit/schemacop/v3/boolean_node_test.rb".freeze, "test/unit/schemacop/v3/global_context_test.rb".freeze, "test/unit/schemacop/v3/hash_node_test.rb".freeze, "test/unit/schemacop/v3/integer_node_test.rb".freeze, "test/unit/schemacop/v3/is_not_node_test.rb".freeze, "test/unit/schemacop/v3/node_test.rb".freeze, "test/unit/schemacop/v3/number_node_test.rb".freeze, "test/unit/schemacop/v3/object_node_test.rb".freeze, "test/unit/schemacop/v3/one_of_node_test.rb".freeze, "test/unit/schemacop/v3/reference_node_test.rb".freeze, "test/unit/schemacop/v3/string_node_test.rb".freeze, "test/unit/schemacop/v3/symbol_node_test.rb".freeze]
|
13
13
|
s.homepage = "https://github.com/sitrox/schemacop".freeze
|
14
14
|
s.licenses = ["MIT".freeze]
|
@@ -27,7 +27,7 @@ Gem::Specification.new do |s|
|
|
27
27
|
s.add_development_dependency(%q<minitest>.freeze, [">= 0"])
|
28
28
|
s.add_development_dependency(%q<minitest-reporters>.freeze, [">= 0"])
|
29
29
|
s.add_development_dependency(%q<colorize>.freeze, [">= 0"])
|
30
|
-
s.add_development_dependency(%q<rubocop>.freeze, ["=
|
30
|
+
s.add_development_dependency(%q<rubocop>.freeze, ["= 1.24.1"])
|
31
31
|
s.add_development_dependency(%q<pry>.freeze, [">= 0"])
|
32
32
|
s.add_development_dependency(%q<byebug>.freeze, [">= 0"])
|
33
33
|
s.add_development_dependency(%q<simplecov>.freeze, ["= 0.21.2"])
|
@@ -39,7 +39,7 @@ Gem::Specification.new do |s|
|
|
39
39
|
s.add_dependency(%q<minitest>.freeze, [">= 0"])
|
40
40
|
s.add_dependency(%q<minitest-reporters>.freeze, [">= 0"])
|
41
41
|
s.add_dependency(%q<colorize>.freeze, [">= 0"])
|
42
|
-
s.add_dependency(%q<rubocop>.freeze, ["=
|
42
|
+
s.add_dependency(%q<rubocop>.freeze, ["= 1.24.1"])
|
43
43
|
s.add_dependency(%q<pry>.freeze, [">= 0"])
|
44
44
|
s.add_dependency(%q<byebug>.freeze, [">= 0"])
|
45
45
|
s.add_dependency(%q<simplecov>.freeze, ["= 0.21.2"])
|
@@ -52,7 +52,7 @@ Gem::Specification.new do |s|
|
|
52
52
|
s.add_dependency(%q<minitest>.freeze, [">= 0"])
|
53
53
|
s.add_dependency(%q<minitest-reporters>.freeze, [">= 0"])
|
54
54
|
s.add_dependency(%q<colorize>.freeze, [">= 0"])
|
55
|
-
s.add_dependency(%q<rubocop>.freeze, ["=
|
55
|
+
s.add_dependency(%q<rubocop>.freeze, ["= 1.24.1"])
|
56
56
|
s.add_dependency(%q<pry>.freeze, [">= 0"])
|
57
57
|
s.add_dependency(%q<byebug>.freeze, [">= 0"])
|
58
58
|
s.add_dependency(%q<simplecov>.freeze, ["= 0.21.2"])
|
@@ -462,6 +462,112 @@ module Schemacop
|
|
462
462
|
end
|
463
463
|
end
|
464
464
|
|
465
|
+
def test_reject_with_symbol
|
466
|
+
schema :array, min_items: 3, max_items: 3, reject: :blank? do
|
467
|
+
list :symbol
|
468
|
+
end
|
469
|
+
|
470
|
+
input = [:foo, :bar, :baz, :'']
|
471
|
+
input_was = input.dup
|
472
|
+
|
473
|
+
assert_validation(input)
|
474
|
+
assert_cast(input, %i[foo bar baz])
|
475
|
+
|
476
|
+
assert_equal input, input_was
|
477
|
+
end
|
478
|
+
|
479
|
+
def test_reject_with_proc
|
480
|
+
schema :array, reject: ->(i) { i > 5 } do
|
481
|
+
list :integer, maximum: 5
|
482
|
+
end
|
483
|
+
|
484
|
+
input = [1, 2, 3, 4, 5, 6]
|
485
|
+
input_was = input.dup
|
486
|
+
|
487
|
+
assert_validation(input)
|
488
|
+
assert_cast(input, [1, 2, 3, 4, 5])
|
489
|
+
|
490
|
+
assert_equal input, input_was
|
491
|
+
end
|
492
|
+
|
493
|
+
def test_reject_with_argument_error
|
494
|
+
schema :array, reject: :zero? do
|
495
|
+
list :integer
|
496
|
+
end
|
497
|
+
|
498
|
+
assert_validation([0, 1, 2, :a]) do
|
499
|
+
error '/[2]', 'Invalid type, got type "Symbol", expected "integer".'
|
500
|
+
end
|
501
|
+
end
|
502
|
+
|
503
|
+
def test_filter_with_symbol
|
504
|
+
schema :array, min_items: 3, max_items: 3, filter: :present? do
|
505
|
+
list :symbol
|
506
|
+
end
|
507
|
+
|
508
|
+
input = [:foo, :bar, :baz, :'']
|
509
|
+
input_was = input.dup
|
510
|
+
|
511
|
+
assert_validation(input)
|
512
|
+
assert_cast(input, %i[foo bar baz])
|
513
|
+
|
514
|
+
assert_equal input, input_was
|
515
|
+
end
|
516
|
+
|
517
|
+
def test_filter_with_proc
|
518
|
+
schema :array, filter: ->(i) { i <= 5 } do
|
519
|
+
list :integer, maximum: 5
|
520
|
+
end
|
521
|
+
|
522
|
+
input = [1, 2, 3, 4, 5, 6]
|
523
|
+
input_was = input.dup
|
524
|
+
|
525
|
+
assert_validation(input)
|
526
|
+
assert_cast(input, [1, 2, 3, 4, 5])
|
527
|
+
|
528
|
+
assert_equal input, input_was
|
529
|
+
end
|
530
|
+
|
531
|
+
def test_filter_with_argument_error
|
532
|
+
schema :array, filter: :nonzero? do
|
533
|
+
list :integer
|
534
|
+
end
|
535
|
+
|
536
|
+
assert_validation([0, 1, 2, :a]) do
|
537
|
+
error '/[2]', 'Invalid type, got type "Symbol", expected "integer".'
|
538
|
+
end
|
539
|
+
end
|
540
|
+
|
541
|
+
def test_doc_example_reject_blank
|
542
|
+
# FYI: This example requires active_support for the blank? method
|
543
|
+
schema = Schemacop::Schema3.new :array, reject: :blank? do
|
544
|
+
list :string
|
545
|
+
end
|
546
|
+
|
547
|
+
assert_equal ['foo'], schema.validate!(['', 'foo'])
|
548
|
+
end
|
549
|
+
|
550
|
+
def test_doc_example_filter_proc
|
551
|
+
schema = Schemacop::Schema3.new :array, filter: ->(value) { value.is_a?(String) } do
|
552
|
+
list :string
|
553
|
+
end
|
554
|
+
|
555
|
+
assert_equal ['foo'], schema.validate!(['foo', 42])
|
556
|
+
end
|
557
|
+
|
558
|
+
def test_doc_example_reject_zero
|
559
|
+
schema = Schemacop::Schema3.new :array, reject: :zero? do
|
560
|
+
list :integer
|
561
|
+
end
|
562
|
+
|
563
|
+
assert_raises_with_message(
|
564
|
+
Schemacop::Exceptions::ValidationError,
|
565
|
+
'/[0]: Invalid type, got type "String", expected "integer".'
|
566
|
+
) do
|
567
|
+
schema.validate!(['foo', 42, 0])
|
568
|
+
end
|
569
|
+
end
|
570
|
+
|
465
571
|
def test_contains
|
466
572
|
schema :array do
|
467
573
|
cont :string
|
@@ -5,7 +5,7 @@ module Schemacop
|
|
5
5
|
module V3
|
6
6
|
class BooleanNodeTest < V3Test
|
7
7
|
def self.invalid_type_error(type)
|
8
|
-
type = type.class unless type.
|
8
|
+
type = type.class unless type.instance_of?(Class)
|
9
9
|
"Invalid type, got type \"#{type}\", expected \"boolean\"."
|
10
10
|
end
|
11
11
|
|
@@ -53,9 +53,9 @@ module Schemacop
|
|
53
53
|
def test_file_reload
|
54
54
|
dir = Dir.mktmpdir
|
55
55
|
Schemacop.load_paths << dir
|
56
|
-
|
56
|
+
File.write(File.join(dir, 'foo.rb'), %(schema :string))
|
57
57
|
assert_is_a StringNode, GlobalContext.instance.schema_for('foo')
|
58
|
-
|
58
|
+
File.write(File.join(dir, 'foo.rb'), %(schema :integer))
|
59
59
|
assert_is_a IntegerNode, GlobalContext.instance.schema_for('foo')
|
60
60
|
end
|
61
61
|
|
@@ -63,12 +63,12 @@ module Schemacop
|
|
63
63
|
dir = Dir.mktmpdir
|
64
64
|
Schemacop.load_paths << dir
|
65
65
|
|
66
|
-
|
66
|
+
File.write(File.join(dir, 'foo.rb'), %(schema :string))
|
67
67
|
|
68
68
|
GlobalContext.instance.eager_load!
|
69
69
|
|
70
70
|
assert_is_a StringNode, GlobalContext.instance.schema_for('foo')
|
71
|
-
|
71
|
+
File.write(File.join(dir, 'foo.rb'), %(schema :integer))
|
72
72
|
assert_is_a StringNode, GlobalContext.instance.schema_for('foo')
|
73
73
|
end
|
74
74
|
|
@@ -117,7 +117,7 @@ module Schemacop
|
|
117
117
|
def test_empty_schema
|
118
118
|
dir = Dir.mktmpdir
|
119
119
|
Schemacop.load_paths << dir
|
120
|
-
|
120
|
+
File.write(File.join(dir, 'foo.rb'), %())
|
121
121
|
assert_raises_with_message RuntimeError, /does not define any schema/ do
|
122
122
|
GlobalContext.instance.schema_for('foo')
|
123
123
|
end
|
@@ -126,7 +126,7 @@ module Schemacop
|
|
126
126
|
def test_multiple_schemas
|
127
127
|
dir = Dir.mktmpdir
|
128
128
|
Schemacop.load_paths << dir
|
129
|
-
|
129
|
+
File.write(File.join(dir, 'foo.rb'), %(schema :string\nschema :integer))
|
130
130
|
assert_raises_with_message RuntimeError, /Schema "#{File.join(dir, 'foo.rb')}" defines multiple schemas/ do
|
131
131
|
GlobalContext.instance.schema_for('foo')
|
132
132
|
end
|
@@ -135,7 +135,7 @@ module Schemacop
|
|
135
135
|
def test_invalid_schema
|
136
136
|
dir = Dir.mktmpdir
|
137
137
|
Schemacop.load_paths << dir
|
138
|
-
|
138
|
+
File.write(File.join(dir, 'foo.rb'), %(foobarbaz))
|
139
139
|
|
140
140
|
assert_raises_with_message RuntimeError, /Could not load schema/ do
|
141
141
|
GlobalContext.schema_for('foo')
|
@@ -145,7 +145,7 @@ module Schemacop
|
|
145
145
|
def test_overrides_with_eager_load
|
146
146
|
dir = Dir.mktmpdir
|
147
147
|
Schemacop.load_paths << dir
|
148
|
-
|
148
|
+
File.write(File.join(dir, 'user.rb'), %(schema :string))
|
149
149
|
|
150
150
|
assert_raises_with_message RuntimeError, %r{in both load paths "test/schemas" and "#{dir}"} do
|
151
151
|
GlobalContext.eager_load!
|
@@ -155,7 +155,7 @@ module Schemacop
|
|
155
155
|
def test_overrides_with_lazy_load
|
156
156
|
dir = Dir.mktmpdir
|
157
157
|
Schemacop.load_paths << dir
|
158
|
-
|
158
|
+
File.write(File.join(dir, 'user.rb'), %(schema :string))
|
159
159
|
|
160
160
|
assert_raises_with_message RuntimeError, %r{in both load paths "test/schemas" and "#{dir}"} do
|
161
161
|
GlobalContext.instance.schema_for('user')
|
@@ -181,6 +181,14 @@ module Schemacop
|
|
181
181
|
|
182
182
|
assert_equal(@schema.root.children, [])
|
183
183
|
end
|
184
|
+
|
185
|
+
def test_default_options
|
186
|
+
Schemacop.v3_default_options = { cast_str: true }.freeze
|
187
|
+
schema :number
|
188
|
+
assert_cast('1', 1)
|
189
|
+
ensure
|
190
|
+
Schemacop.v3_default_options = {}
|
191
|
+
end
|
184
192
|
end
|
185
193
|
end
|
186
194
|
end
|
@@ -158,6 +158,14 @@ module Schemacop
|
|
158
158
|
assert_cast('2018-11-13T20:20:39+00:00', DateTime.new(2018, 11, 13, 20, 20, 39))
|
159
159
|
end
|
160
160
|
|
161
|
+
def test_format_time
|
162
|
+
schema :string, format: :time
|
163
|
+
assert_json(type: :string, format: :time)
|
164
|
+
assert_cast '20:30:39+00:00', Time.strptime('20:30:39+00:00', '%H:%M:%S%z')
|
165
|
+
|
166
|
+
assert_cast nil, nil
|
167
|
+
end
|
168
|
+
|
161
169
|
def test_format_email
|
162
170
|
schema :string, format: :email
|
163
171
|
|
@@ -183,6 +191,17 @@ module Schemacop
|
|
183
191
|
assert_cast('john.doe@example.com', 'john.doe@example.com')
|
184
192
|
end
|
185
193
|
|
194
|
+
def test_format_boolean
|
195
|
+
schema :string, format: :boolean
|
196
|
+
|
197
|
+
assert_json(type: :string, format: :boolean)
|
198
|
+
|
199
|
+
assert_cast 'true', true
|
200
|
+
assert_cast 'false', false
|
201
|
+
|
202
|
+
assert_cast nil, nil
|
203
|
+
end
|
204
|
+
|
186
205
|
def test_format_symbol
|
187
206
|
schema :string, format: :symbol
|
188
207
|
|
@@ -200,6 +219,28 @@ module Schemacop
|
|
200
219
|
assert_cast('039n23$g- sfk3/', :'039n23$g- sfk3/')
|
201
220
|
end
|
202
221
|
|
222
|
+
def test_format_integer
|
223
|
+
schema :string, format: :integer
|
224
|
+
|
225
|
+
assert_json(type: :string, format: :integer)
|
226
|
+
|
227
|
+
assert_validation '23425'
|
228
|
+
assert_validation '-23425'
|
229
|
+
|
230
|
+
assert_validation 12_312 do
|
231
|
+
error '/', StringNodeTest.invalid_type_error(Integer)
|
232
|
+
end
|
233
|
+
|
234
|
+
assert_validation '24.32' do
|
235
|
+
error '/', 'String does not match format "integer".'
|
236
|
+
end
|
237
|
+
|
238
|
+
assert_cast(nil, nil)
|
239
|
+
assert_cast('2234', 2234)
|
240
|
+
assert_cast('-1', -1)
|
241
|
+
assert_cast('-0', 0)
|
242
|
+
end
|
243
|
+
|
203
244
|
def test_format_integer_list
|
204
245
|
schema :string, format: :integer_list
|
205
246
|
|
@@ -222,6 +263,38 @@ module Schemacop
|
|
222
263
|
assert_cast '1,-2,3', [1, -2, 3]
|
223
264
|
assert_cast '1', [1]
|
224
265
|
assert_cast '-1', [-1]
|
266
|
+
assert_cast '08', [8]
|
267
|
+
assert_cast '09', [9]
|
268
|
+
assert_cast '050', [50]
|
269
|
+
assert_cast '01,032', [1, 32]
|
270
|
+
end
|
271
|
+
|
272
|
+
def test_format_custom
|
273
|
+
Schemacop.register_string_formatter(
|
274
|
+
:integer_tuple_list,
|
275
|
+
pattern: /^(-?[0-9]+):(-?[0-9]+)(,(-?[0-9]+):(-?[0-9]+))*$/,
|
276
|
+
handler: proc do |value|
|
277
|
+
value.split(',').map { |t| t.split(':').map(&:to_i) }
|
278
|
+
end
|
279
|
+
)
|
280
|
+
|
281
|
+
schema :string, format: :integer_tuple_list
|
282
|
+
|
283
|
+
assert_json(type: :string, format: :'integer-tuple-list')
|
284
|
+
|
285
|
+
assert_validation '1:5,4:2,-4:4,4:-1,0:0'
|
286
|
+
assert_validation '-1:5'
|
287
|
+
|
288
|
+
assert_validation 234 do
|
289
|
+
error '/', StringNodeTest.invalid_type_error(Integer)
|
290
|
+
end
|
291
|
+
|
292
|
+
assert_validation 'sd sfdij soidf' do
|
293
|
+
error '/', 'String does not match format "integer-tuple-list".'
|
294
|
+
end
|
295
|
+
|
296
|
+
assert_cast nil, nil
|
297
|
+
assert_cast '1:2,3:4,5:-6', [[1, 2], [3, 4], [5, -6]]
|
225
298
|
end
|
226
299
|
|
227
300
|
def test_enum
|
@@ -248,33 +321,6 @@ module Schemacop
|
|
248
321
|
end
|
249
322
|
end
|
250
323
|
|
251
|
-
def test_boolean_casting
|
252
|
-
schema :string, format: :boolean
|
253
|
-
|
254
|
-
assert_json(type: :string, format: :boolean)
|
255
|
-
|
256
|
-
assert_cast 'true', true
|
257
|
-
assert_cast 'false', false
|
258
|
-
|
259
|
-
assert_cast nil, nil
|
260
|
-
end
|
261
|
-
|
262
|
-
def test_time_casting
|
263
|
-
schema :string, format: :time
|
264
|
-
assert_json(type: :string, format: :time)
|
265
|
-
assert_cast '20:30:39+00:00', Time.strptime('20:30:39+00:00', '%H:%M:%S%z')
|
266
|
-
|
267
|
-
assert_cast nil, nil
|
268
|
-
end
|
269
|
-
|
270
|
-
def test_date_casting
|
271
|
-
schema :string, format: :date
|
272
|
-
assert_json(type: :string, format: :date)
|
273
|
-
assert_cast '2018-11-13', Date.new(2018, 11, 13)
|
274
|
-
|
275
|
-
assert_cast nil, nil
|
276
|
-
end
|
277
|
-
|
278
324
|
def test_date_time_casting
|
279
325
|
schema :string, format: :date_time
|
280
326
|
assert_json(type: :string, format: :'date-time')
|
@@ -4,7 +4,7 @@ module Schemacop
|
|
4
4
|
module V3
|
5
5
|
class SymbolNodeTest < V3Test
|
6
6
|
def self.invalid_type_error(type)
|
7
|
-
type = type.class unless type.
|
7
|
+
type = type.class unless type.instance_of?(Class)
|
8
8
|
"Invalid type, got type \"#{type}\", expected \"Symbol\"."
|
9
9
|
end
|
10
10
|
|
@@ -25,7 +25,7 @@ module Schemacop
|
|
25
25
|
def test_required
|
26
26
|
schema :symbol, required: true
|
27
27
|
assert_validation :foo
|
28
|
-
assert_validation
|
28
|
+
assert_validation :""
|
29
29
|
assert_validation nil do
|
30
30
|
error '/', 'Value must be given.'
|
31
31
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: schemacop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.17
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sitrox
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-06-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -114,14 +114,14 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - '='
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
117
|
+
version: 1.24.1
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - '='
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
124
|
+
version: 1.24.1
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: pry
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -164,8 +164,8 @@ dependencies:
|
|
164
164
|
- - '='
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: 0.21.2
|
167
|
-
description:
|
168
|
-
email:
|
167
|
+
description:
|
168
|
+
email:
|
169
169
|
executables: []
|
170
170
|
extensions: []
|
171
171
|
extra_rdoc_files: []
|
@@ -277,7 +277,7 @@ homepage: https://github.com/sitrox/schemacop
|
|
277
277
|
licenses:
|
278
278
|
- MIT
|
279
279
|
metadata: {}
|
280
|
-
post_install_message:
|
280
|
+
post_install_message:
|
281
281
|
rdoc_options: []
|
282
282
|
require_paths:
|
283
283
|
- lib
|
@@ -292,8 +292,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
292
292
|
- !ruby/object:Gem::Version
|
293
293
|
version: '0'
|
294
294
|
requirements: []
|
295
|
-
rubygems_version: 3.
|
296
|
-
signing_key:
|
295
|
+
rubygems_version: 3.3.11
|
296
|
+
signing_key:
|
297
297
|
specification_version: 4
|
298
298
|
summary: Schemacop validates ruby structures consisting of nested hashes and arrays
|
299
299
|
against simple schema definitions.
|