schemacop 3.0.0.rc1 → 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/CHANGELOG.md +14 -0
- data/README_V3.md +188 -44
- data/VERSION +1 -1
- data/lib/schemacop/v3/array_node.rb +1 -2
- data/lib/schemacop/v3/hash_node.rb +31 -13
- data/lib/schemacop/v3/node.rb +1 -0
- data/schemacop.gemspec +3 -3
- data/test/unit/schemacop/v3/all_of_node_test.rb +1 -2
- data/test/unit/schemacop/v3/any_of_node_test.rb +6 -6
- data/test/unit/schemacop/v3/array_node_test.rb +13 -3
- data/test/unit/schemacop/v3/hash_node_test.rb +78 -20
- data/test/unit/schemacop/v3/one_of_node_test.rb +6 -6
- data/test/unit/schemacop/v3/reference_node_test.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73279c1805de5438933af200c883a7f6a813878d583c92bf7e597580f392df95
|
4
|
+
data.tar.gz: 2ac5ce2925de12c5df8a4f82086d967c68d31cd9f8c598cff0da9231d221f5ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c04434b491dac3c09018969b13293c029347011a58386234ea5dcca6b3aa7ed8ebe3f291b8d819869d79b3c8c80d5a998bbbca0a95d928988367e04efcad4ec2
|
7
|
+
data.tar.gz: 75564dd05800d295f3eb7ebb606f97ea67f2c19512a62193d49651cc77828836cfa95977465692ac85a5738a8407c7a2275a7cbe34db110c8400e70aa5057e95
|
data/CHANGELOG.md
CHANGED
@@ -10,6 +10,20 @@
|
|
10
10
|
### Changes
|
11
11
|
-->
|
12
12
|
|
13
|
+
## 3.0.0.r2
|
14
|
+
|
15
|
+
* Represent node names as strings internally
|
16
|
+
|
17
|
+
* Update documentation
|
18
|
+
|
19
|
+
## 3.0.0.rc1
|
20
|
+
|
21
|
+
* Add support for ruby `3.0.0`
|
22
|
+
|
23
|
+
* Add `ruby-3.0.0` to travis testing
|
24
|
+
|
25
|
+
* Document all `v3` nodes
|
26
|
+
|
13
27
|
## 3.0.0.rc0
|
14
28
|
|
15
29
|
* Add `Schemacop::Schema3`
|
data/README_V3.md
CHANGED
@@ -1,15 +1,11 @@
|
|
1
1
|
# Schemacop schema V3
|
2
2
|
|
3
|
-
|
3
|
+
## Table of Contents
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
2. [Validation](#validation)
|
10
|
-
3. [Exceptions](#exceptions)
|
11
|
-
4. [Generic Keywords](#generic-keywords)
|
12
|
-
5. [Nodes](#nodes)
|
5
|
+
1. [Validation](#validation)
|
6
|
+
2. [Exceptions](#exceptions)
|
7
|
+
3. [Generic Keywords](#generic-keywords)
|
8
|
+
4. [Nodes](#nodes)
|
13
9
|
1. [String](#string)
|
14
10
|
2. [Integer](#integer)
|
15
11
|
3. [Number](#number)
|
@@ -23,12 +19,8 @@ Use at your own discretion.
|
|
23
19
|
11. [OneOf](#oneOf)
|
24
20
|
12. [IsNot](#isNot)
|
25
21
|
13. [Reference](#reference)
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
## Introduction
|
30
|
-
|
31
|
-
TODO: Write short section about using schemacop V3
|
22
|
+
5. [Context](#context)
|
23
|
+
6. [External schemas](#external-schemas)
|
32
24
|
|
33
25
|
## Validation
|
34
26
|
|
@@ -74,19 +66,121 @@ schema.validate!('Foo') # => Schemacop::Exceptions::ValidationError: /:
|
|
74
66
|
|
75
67
|
## Exceptions
|
76
68
|
|
77
|
-
|
69
|
+
Schemacop can raise the following exceptions:
|
78
70
|
|
79
|
-
`Schemacop::Exceptions::ValidationError`
|
80
|
-
|
71
|
+
* `Schemacop::Exceptions::ValidationError`: This exception is raised when the `validate!`
|
72
|
+
method is used, and the data that was passed in is invalid. The exception message contains
|
73
|
+
additional informations why the validation failed.
|
74
|
+
|
75
|
+
Example:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
schema = Schemacop::Schema3.new :hash do
|
79
|
+
int! :foo
|
80
|
+
end
|
81
|
+
|
82
|
+
schema.validate!(foo: 'bar')
|
83
|
+
# => Schemacop::Exceptions::ValidationError: /foo: Invalid type, expected "integer".
|
84
|
+
```
|
85
|
+
|
86
|
+
* `Schemacop::Exceptions::InvalidSchemaError`: This exception is raised when the schema
|
87
|
+
itself is not valid. The exception message contains additional informations why the
|
88
|
+
validation failed.
|
89
|
+
|
90
|
+
Example:
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
Schemacop::Schema3.new :hash do
|
94
|
+
int!
|
95
|
+
end
|
96
|
+
|
97
|
+
# => Schemacop::Exceptions::InvalidSchemaError: Child nodes must have a name.
|
98
|
+
```
|
81
99
|
|
82
100
|
## Generic Keywords
|
83
101
|
|
84
|
-
|
102
|
+
The nodes in Schemacop v3 also support generic keywords, similar to JSON schema:
|
103
|
+
|
104
|
+
* `title`: Short string, should be self-explanatory
|
105
|
+
* `description`: Description of the schema
|
106
|
+
* `examples`: Here, you can provide examples which will be valid for the schema
|
107
|
+
* `enum`: Here, you may enumerate values which will be valid, if the provided
|
108
|
+
value is not in the array, the validation will fail
|
109
|
+
* `default`: You may provide a default value for items that will be set if the
|
110
|
+
value is not given
|
111
|
+
|
112
|
+
|
113
|
+
The three keywords `title`, `description` and `examples` aren't used for validation,
|
114
|
+
but can be used to document the schema. They will be included in the JSON output
|
115
|
+
when you use the `as_json` method:
|
116
|
+
|
117
|
+
```ruby
|
118
|
+
schema = Schemacop::Schema3.new :hash do
|
119
|
+
str! :name, title: 'Name', description: 'Holds the name of the user', examples: ['Joe', 'Anna']
|
120
|
+
end
|
121
|
+
|
122
|
+
schema.as_json
|
123
|
+
|
124
|
+
# => {"properties"=>{"name"=>{"type"=>"string", "title"=>"Name", "examples"=>["Joe", "Anna"], "description"=>"Holds the name of the user"}}, "additionalProperties"=>false, "required"=>["name"], "type"=>"object"}
|
125
|
+
```
|
126
|
+
|
127
|
+
The `enum` keyword can be used to only allow a subset of values:
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
schema = Schemacop::Schema3.new :string, enum: ['foo', 'bar']
|
131
|
+
|
132
|
+
schema.validate!('foo') # => "foo"
|
133
|
+
schema.validate!('bar') # => "bar"
|
134
|
+
schema.validate!('baz') # => Schemacop::Exceptions::ValidationError: /: Value not included in enum ["foo", "bar"].
|
135
|
+
```
|
136
|
+
|
137
|
+
Please note, that you can also specify values in the enum that are not valid for
|
138
|
+
the schema. This means that the validation will still fail:
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
schema = Schemacop::Schema3.new :string, enum: ['foo', 'bar', 42]
|
142
|
+
|
143
|
+
schema.validate!('foo') # => "foo"
|
144
|
+
schema.validate!('bar') # => "bar"
|
145
|
+
schema.validate!(42) # => Schemacop::Exceptions::ValidationError: /: Invalid type, expected "string".
|
146
|
+
```
|
147
|
+
|
148
|
+
The enum will also be provided in the json output:
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
schema = Schemacop::Schema3.new :string, enum: ['foo', 'bar']
|
152
|
+
|
153
|
+
schema.as_json
|
154
|
+
# => {"type"=>"string", "enum"=>["foo", "bar", 42]}
|
155
|
+
```
|
156
|
+
|
157
|
+
And finally, the `default` keyword lets you set a default value to use when no
|
158
|
+
value is provided:
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
schema = Schemacop::Schema3.new :string, default: 'Schemacop'
|
162
|
+
|
163
|
+
schema.validate!('foo') # => "foo"
|
164
|
+
schema.validate!(nil) # => "Schemacop"
|
165
|
+
```
|
166
|
+
|
167
|
+
The default value will also be provided in the json output:
|
85
168
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
169
|
+
```ruby
|
170
|
+
schema = Schemacop::Schema3.new :string, default: 'Schemacop'
|
171
|
+
|
172
|
+
schema.as_json
|
173
|
+
# => {"type"=>"string", "default"=>"Schemacop"}
|
174
|
+
```
|
175
|
+
|
176
|
+
Note that the default value you use is also validated against the schema:
|
177
|
+
|
178
|
+
```ruby
|
179
|
+
schema = Schemacop::Schema3.new :string, default: 42
|
180
|
+
|
181
|
+
schema.validate!('foo') # => "foo"
|
182
|
+
schema.validate!(nil) # => Schemacop::Exceptions::ValidationError: /: Invalid type, expected "string".
|
183
|
+
```
|
90
184
|
|
91
185
|
## Nodes
|
92
186
|
|
@@ -523,11 +617,61 @@ schema = Schemacop::Schema3.new :hash do
|
|
523
617
|
end
|
524
618
|
|
525
619
|
schema.validate!({}) # => Schemacop::Exceptions::ValidationError: /foo: Value must be given.
|
526
|
-
schema.validate!({foo: 'str'}) # => {
|
527
|
-
schema.validate!({foo: 'str', bar: 42}) # => {
|
620
|
+
schema.validate!({foo: 'str'}) # => {"foo"=>"str"}
|
621
|
+
schema.validate!({foo: 'str', bar: 42}) # => {"foo"=>"str", "bar"=>42}
|
528
622
|
schema.validate!({bar: 42}) # => Schemacop::Exceptions::ValidationError: /foo: Value must be given.
|
529
623
|
```
|
530
624
|
|
625
|
+
The name of the properties may either be a string or a symbol, and you can pass
|
626
|
+
in the property either identified by a symbol or a string:
|
627
|
+
|
628
|
+
The following two schemas are equal:
|
629
|
+
|
630
|
+
```ruby
|
631
|
+
schema = Schemacop::Schema3.new :hash do
|
632
|
+
int! :foo
|
633
|
+
end
|
634
|
+
|
635
|
+
schema.validate!(foo: 42) # => {"foo"=>42}
|
636
|
+
schema.validate!('foo' => 42) # => {"foo"=>42}
|
637
|
+
|
638
|
+
schema = Schemacop::Schema3.new :hash do
|
639
|
+
int! 'foo'
|
640
|
+
end
|
641
|
+
|
642
|
+
schema.validate!(foo: 42) # => {"foo"=>42}
|
643
|
+
schema.validate!('foo' => 42) # => {"foo"=>42}
|
644
|
+
```
|
645
|
+
|
646
|
+
The result in both cases will be a
|
647
|
+
[HashWithIndifferentAccess](https://api.rubyonrails.org/classes/ActiveSupport/HashWithIndifferentAccess.html),
|
648
|
+
which means that you can access the data in the hash with the symbol as well
|
649
|
+
as the string representation:
|
650
|
+
|
651
|
+
```ruby
|
652
|
+
schema = Schemacop::Schema3.new :hash do
|
653
|
+
int! :foo
|
654
|
+
end
|
655
|
+
|
656
|
+
result = schema.validate!(foo: 42)
|
657
|
+
|
658
|
+
result.class # => ActiveSupport::HashWithIndifferentAccess
|
659
|
+
result[:foo] # => 42
|
660
|
+
result['foo'] # 42
|
661
|
+
```
|
662
|
+
|
663
|
+
Please note, that if you specify the value twice in the data you want to validate,
|
664
|
+
once with the key being a symbol and once being a string, Schemacop will raise an
|
665
|
+
error:
|
666
|
+
|
667
|
+
```ruby
|
668
|
+
schema = Schemacop::Schema3.new :hash do
|
669
|
+
int! :foo
|
670
|
+
end
|
671
|
+
|
672
|
+
schema.validate!(foo: 42, 'foo' => 43) # => Schemacop::Exceptions::ValidationError: /: Has 1 ambiguous properties: [:foo].
|
673
|
+
```
|
674
|
+
|
531
675
|
##### Pattern properties
|
532
676
|
|
533
677
|
In addition to symbols, property keys can also be a regular expression. Here,
|
@@ -543,8 +687,8 @@ schema = Schemacop::Schema3.new :hash do
|
|
543
687
|
end
|
544
688
|
|
545
689
|
schema.validate!({}) # => {}
|
546
|
-
schema.validate!({id_foo: 1}) # => {
|
547
|
-
schema.validate!({id_foo: 1, id_bar: 2}) # => {
|
690
|
+
schema.validate!({id_foo: 1}) # => {"id_foo"=>1}
|
691
|
+
schema.validate!({id_foo: 1, id_bar: 2}) # => {"id_foo"=>1, "id_bar"=>2}
|
548
692
|
schema.validate!({foo: 3}) # => Schemacop::Exceptions::ValidationError: /: Obsolete property "foo".
|
549
693
|
```
|
550
694
|
|
@@ -562,7 +706,7 @@ enable all of them by enabling the option `additional_properties`:
|
|
562
706
|
schema = Schemacop::Schema3.new :hash, additional_properties: true
|
563
707
|
|
564
708
|
schema.validate!({}) # => {}
|
565
|
-
schema.validate!({foo: :bar, baz: 42}) # => {
|
709
|
+
schema.validate!({foo: :bar, baz: 42}) # => {"foo"=>:bar, "baz"=>42}
|
566
710
|
```
|
567
711
|
|
568
712
|
Using the DSL method `add` in the hash-node's body however, you can specify
|
@@ -578,8 +722,8 @@ Schemacop::Schema3.new :hash do
|
|
578
722
|
add :string
|
579
723
|
end
|
580
724
|
|
581
|
-
schema.validate!({id: 1}) # => {
|
582
|
-
schema.validate!({id: 1, foo: 'bar'}) # => {
|
725
|
+
schema.validate!({id: 1}) # => {"id"=>1}
|
726
|
+
schema.validate!({id: 1, foo: 'bar'}) # => {"id"=>1, "foo"=>"bar"}
|
583
727
|
schema.validate!({id: 1, foo: 42}) # => Schemacop::Exceptions::ValidationError: /foo: Invalid type, expected "string".
|
584
728
|
```
|
585
729
|
|
@@ -589,12 +733,12 @@ any additional property **keys** must adhere to:
|
|
589
733
|
```ruby
|
590
734
|
# The following schema allows any number of properties, but all keys must
|
591
735
|
# consist of downcase letters from a-z.
|
592
|
-
schema = Schemacop::Schema3.new :hash, additional_properties:
|
736
|
+
schema = Schemacop::Schema3.new :hash, additional_properties: true, property_names: '^[a-z]+$'
|
593
737
|
|
594
738
|
|
595
739
|
schema.validate!({}) # => {}
|
596
|
-
schema.validate!({foo: 123}) # => {
|
597
|
-
schema.validate!({Foo: 'bar'}) # => Schemacop::Exceptions::ValidationError: /: Property name
|
740
|
+
schema.validate!({foo: 123}) # => {"foo"=>123}
|
741
|
+
schema.validate!({Foo: 'bar'}) # => Schemacop::Exceptions::ValidationError: /: Property name "Foo" does not match "^[a-z]+$".
|
598
742
|
|
599
743
|
# The following schema allows any number of properties, but all keys must
|
600
744
|
# consist of downcase letters from a-z AND the properties must be arrays.
|
@@ -603,7 +747,7 @@ schema = Schemacop::Schema3.new :hash, additional_properties: true, property_nam
|
|
603
747
|
end
|
604
748
|
|
605
749
|
schema.validate!({}) # => {}
|
606
|
-
schema.validate!({foo: [1, 2, 3]}) # => {
|
750
|
+
schema.validate!({foo: [1, 2, 3]}) # => {"foo"=>[1, 2, 3]}
|
607
751
|
schema.validate!({foo: :bar}) # => Schemacop::Exceptions::ValidationError: /foo: Invalid type, expected "array".
|
608
752
|
schema.validate!({Foo: :bar}) # => Schemacop::Exceptions::ValidationError: /: Property name :Foo does not match "^[a-z]+$". /Foo: Invalid type, expected "array".
|
609
753
|
```
|
@@ -627,7 +771,7 @@ schema = Schemacop::Schema3.new :hash do
|
|
627
771
|
end
|
628
772
|
|
629
773
|
schema.validate!({}) # => Schemacop::Exceptions::ValidationError: /name: Value must be given.
|
630
|
-
schema.validate!({name: 'Joe Doe'}) # => {
|
774
|
+
schema.validate!({name: 'Joe Doe'}) # => {"name"=>"Joe Doe"}
|
631
775
|
schema.validate!({
|
632
776
|
name: 'Joe Doe',
|
633
777
|
billing_address: 'Street 42'
|
@@ -646,7 +790,7 @@ schema.validate!({
|
|
646
790
|
phone_number: '000-000-00-00',
|
647
791
|
credit_card: 'XXXX XXXX XXXX XXXX X'
|
648
792
|
})
|
649
|
-
# => {
|
793
|
+
# => {"name"=>"Joe Doe", "credit_card"=>"XXXX XXXX XXXX XXXX X", "billing_address"=>"Street 42", "phone_number"=>"000-000-00-00"}
|
650
794
|
```
|
651
795
|
|
652
796
|
### Object
|
@@ -654,7 +798,7 @@ schema.validate!({
|
|
654
798
|
Type: `:object`\
|
655
799
|
DSL: `obj`
|
656
800
|
|
657
|
-
The object type represents a ruby `Object`. Please note that the `as_json
|
801
|
+
The object type represents a ruby `Object`. Please note that the `as_json` method
|
658
802
|
on nodes of this type will just return `{}` (an empty JSON object), as there isn't
|
659
803
|
a useful way to represent a ruby object without conflicting with the `Hash` type.
|
660
804
|
If you want to represent an JSON object, you should use the `Hash` node.
|
@@ -884,7 +1028,7 @@ schema.validate!({
|
|
884
1028
|
}
|
885
1029
|
})
|
886
1030
|
|
887
|
-
# => {
|
1031
|
+
# => {"shipping_address"=>{"street"=>"Example Street 42", "zip_code"=>"12345", "location"=>"London", "country"=>"United Kingdom"}, "billing_address"=>{"street"=>"Main St.", "zip_code"=>"54321", "location"=>"Washington DC", "country"=>"USA"}}
|
888
1032
|
```
|
889
1033
|
|
890
1034
|
Note that if you use the reference node with the long type name `reference`,
|
@@ -902,7 +1046,7 @@ schema = Schemacop::Schema3.new :array do
|
|
902
1046
|
end
|
903
1047
|
|
904
1048
|
schema.validate!([]) # => []
|
905
|
-
schema.validate!([{first_name: 'Joe', last_name: 'Doe'}]) # => [{
|
1049
|
+
schema.validate!([{first_name: 'Joe', last_name: 'Doe'}]) # => [{"first_name"=>"Joe", "last_name"=>"Doe"}]
|
906
1050
|
schema.validate!([id: 42, first_name: 'Joe']) # => Schemacop::Exceptions::ValidationError: /[0]/last_name: Value must be given. /[0]: Obsolete property "id".
|
907
1051
|
```
|
908
1052
|
|
@@ -940,7 +1084,7 @@ schema = Schemacop::Schema3.new :reference, path: :Person
|
|
940
1084
|
# of the person.
|
941
1085
|
Schemacop.with_context context do
|
942
1086
|
schema.validate!({first_name: 'Joe', last_name: 'Doe', info: { born_at: '1980-01-01'} })
|
943
|
-
# => {
|
1087
|
+
# => {"first_name"=>"Joe", "last_name"=>"Doe", "info"=>{"born_at"=>Tue, 01 Jan 1980}}
|
944
1088
|
end
|
945
1089
|
|
946
1090
|
# Now we might want another context, where the person is more anonymous, and as
|
@@ -961,7 +1105,7 @@ Schemacop.with_context other_context do
|
|
961
1105
|
# /: Obsolete property "last_name".
|
962
1106
|
# /: Obsolete property "info".
|
963
1107
|
|
964
|
-
schema.validate!({nickname: 'J.'}) # => {
|
1108
|
+
schema.validate!({nickname: 'J.'}) # => {"nickname"=>"J."}
|
965
1109
|
end
|
966
1110
|
```
|
967
1111
|
|
@@ -1032,13 +1176,13 @@ schema = Schemacop::Schema3.new :hash do
|
|
1032
1176
|
end
|
1033
1177
|
|
1034
1178
|
schema.validate!({usr: {first_name: 'Joe', last_name: 'Doe'}})
|
1035
|
-
# => {
|
1179
|
+
# => {"usr"=>{"first_name"=>"Joe", "last_name"=>"Doe"}}
|
1036
1180
|
|
1037
1181
|
schema.validate!({usr: {first_name: 'Joe', last_name: 'Doe', groups: []}})
|
1038
|
-
# => {
|
1182
|
+
# => {"usr"=>{"first_name"=>"Joe", "last_name"=>"Doe", "groups"=>[]}}
|
1039
1183
|
|
1040
1184
|
schema.validate!({usr: {first_name: 'Joe', last_name: 'Doe', groups: [{name: 'foo'}, {name: 'bar'}]}})
|
1041
|
-
# => {
|
1185
|
+
# => {"usr"=>{"first_name"=>"Joe", "last_name"=>"Doe", "groups"=>[{"name"=>"foo"}, {"name"=>"bar"}]}}
|
1042
1186
|
```
|
1043
1187
|
|
1044
1188
|
### Non-Rails applications
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.0.0.
|
1
|
+
3.0.0.rc2
|
@@ -172,10 +172,9 @@ module Schemacop
|
|
172
172
|
list_item.present?
|
173
173
|
end
|
174
174
|
|
175
|
-
def item_for_data(data
|
175
|
+
def item_for_data(data)
|
176
176
|
item = children.find { |c| item_matches?(c, data) }
|
177
177
|
return item if item
|
178
|
-
return nil unless force
|
179
178
|
|
180
179
|
fail "Could not find specification for item #{data.inspect}."
|
181
180
|
end
|
@@ -91,14 +91,23 @@ module Schemacop
|
|
91
91
|
super_data = super
|
92
92
|
return if super_data.nil?
|
93
93
|
|
94
|
+
original_data_hash = super_data.dup
|
95
|
+
data_hash = super_data.with_indifferent_access
|
96
|
+
|
97
|
+
if original_data_hash.size != data_hash.size
|
98
|
+
ambiguous_properties = original_data_hash.keys - data_hash.keys
|
99
|
+
|
100
|
+
result.error "Has #{ambiguous_properties.size} ambiguous properties: #{ambiguous_properties}."
|
101
|
+
end
|
102
|
+
|
94
103
|
# Validate min_properties #
|
95
|
-
if options[:min_properties] &&
|
96
|
-
result.error "Has #{
|
104
|
+
if options[:min_properties] && data_hash.size < options[:min_properties]
|
105
|
+
result.error "Has #{data_hash.size} properties but needs at least #{options[:min_properties]}."
|
97
106
|
end
|
98
107
|
|
99
108
|
# Validate max_properties #
|
100
|
-
if options[:max_properties] &&
|
101
|
-
result.error "Has #{
|
109
|
+
if options[:max_properties] && data_hash.size > options[:max_properties]
|
110
|
+
result.error "Has #{data_hash.size} properties but needs at most #{options[:max_properties]}."
|
102
111
|
end
|
103
112
|
|
104
113
|
# Validate specified properties #
|
@@ -106,13 +115,13 @@ module Schemacop
|
|
106
115
|
result.in_path(node.name) do
|
107
116
|
next if node.name.is_a?(Regexp)
|
108
117
|
|
109
|
-
node._validate(
|
118
|
+
node._validate(data_hash[node.name], result: result)
|
110
119
|
end
|
111
120
|
end
|
112
121
|
|
113
122
|
# Validate additional properties #
|
114
123
|
specified_properties = @properties.keys.to_set
|
115
|
-
additional_properties =
|
124
|
+
additional_properties = data_hash.reject { |k, _v| specified_properties.include?(k.to_s) }
|
116
125
|
|
117
126
|
property_patterns = {}
|
118
127
|
|
@@ -149,7 +158,7 @@ module Schemacop
|
|
149
158
|
# Validate dependencies #
|
150
159
|
options[:dependencies]&.each do |source, targets|
|
151
160
|
targets.each do |target|
|
152
|
-
if
|
161
|
+
if data_hash[source].present? && data_hash[target].blank?
|
153
162
|
result.error "Missing property #{target.to_s.inspect} because #{source.to_s.inspect} is given."
|
154
163
|
end
|
155
164
|
end
|
@@ -161,10 +170,19 @@ module Schemacop
|
|
161
170
|
end
|
162
171
|
|
163
172
|
def cast(data)
|
164
|
-
result = {}
|
173
|
+
result = {}.with_indifferent_access
|
165
174
|
data ||= default
|
166
175
|
return nil if data.nil?
|
167
176
|
|
177
|
+
original_data_hash = data.dup
|
178
|
+
data_hash = data.with_indifferent_access
|
179
|
+
|
180
|
+
if original_data_hash.size != data_hash.size
|
181
|
+
ambiguous_properties = original_data_hash.keys - data_hash.keys
|
182
|
+
|
183
|
+
result.error "Has #{ambiguous_properties.size} ambiguous properties: #{ambiguous_properties}."
|
184
|
+
end
|
185
|
+
|
168
186
|
property_patterns = {}
|
169
187
|
|
170
188
|
@properties.each_value do |prop|
|
@@ -173,16 +191,16 @@ module Schemacop
|
|
173
191
|
next
|
174
192
|
end
|
175
193
|
|
176
|
-
result[prop.name] = prop.cast(
|
194
|
+
result[prop.name] = prop.cast(data_hash[prop.name])
|
177
195
|
|
178
|
-
if result[prop.name].nil? && !
|
196
|
+
if result[prop.name].nil? && !data_hash.include?(prop.name)
|
179
197
|
result.delete(prop.name)
|
180
198
|
end
|
181
199
|
end
|
182
200
|
|
183
201
|
# Handle regex properties
|
184
202
|
specified_properties = @properties.keys.to_set
|
185
|
-
additional_properties =
|
203
|
+
additional_properties = data_hash.reject { |k, _v| specified_properties.include?(k.to_s.to_sym) }
|
186
204
|
|
187
205
|
if additional_properties.any? && property_patterns.any?
|
188
206
|
additional_properties.each do |name, additional_property|
|
@@ -194,10 +212,10 @@ module Schemacop
|
|
194
212
|
|
195
213
|
# Handle additional properties
|
196
214
|
if options[:additional_properties] == true
|
197
|
-
result =
|
215
|
+
result = data_hash.merge(result)
|
198
216
|
elsif options[:additional_properties].is_a?(Node)
|
199
217
|
specified_properties = @properties.keys.to_set
|
200
|
-
additional_properties =
|
218
|
+
additional_properties = data_hash.reject { |k, _v| specified_properties.include?(k.to_s.to_sym) }
|
201
219
|
if additional_properties.any?
|
202
220
|
additional_properties_result = {}
|
203
221
|
additional_properties.each do |key, value|
|
data/lib/schemacop/v3/node.rb
CHANGED
data/schemacop.gemspec
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
# stub: schemacop 3.0.0.
|
2
|
+
# stub: schemacop 3.0.0.rc2 ruby lib
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "schemacop".freeze
|
6
|
-
s.version = "3.0.0.
|
6
|
+
s.version = "3.0.0.rc2"
|
7
7
|
|
8
8
|
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1".freeze) if s.respond_to? :required_rubygems_version=
|
9
9
|
s.require_paths = ["lib".freeze]
|
10
10
|
s.authors = ["Sitrox".freeze]
|
11
|
-
s.date = "2021-01-
|
11
|
+
s.date = "2021-01-28"
|
12
12
|
s.files = [".gitignore".freeze, ".releaser_config".freeze, ".rubocop.yml".freeze, ".travis.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/root_node.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]
|
@@ -133,11 +133,11 @@ module Schemacop
|
|
133
133
|
|
134
134
|
assert_cast(
|
135
135
|
{ created_at: '2020-01-01' },
|
136
|
-
created_at: Date.new(2020, 1, 1)
|
136
|
+
{ created_at: Date.new(2020, 1, 1) }.with_indifferent_access
|
137
137
|
)
|
138
138
|
assert_cast(
|
139
139
|
{ created_at: '2020-01-01T17:38:20' },
|
140
|
-
created_at: DateTime.new(2020, 1, 1, 17, 38, 20)
|
140
|
+
{ created_at: DateTime.new(2020, 1, 1, 17, 38, 20) }.with_indifferent_access
|
141
141
|
)
|
142
142
|
end
|
143
143
|
|
@@ -158,12 +158,12 @@ module Schemacop
|
|
158
158
|
|
159
159
|
assert_cast(
|
160
160
|
{ foo: { bar: nil } },
|
161
|
-
foo: { bar: nil }
|
161
|
+
{ foo: { bar: nil } }.with_indifferent_access
|
162
162
|
)
|
163
163
|
|
164
164
|
assert_cast(
|
165
165
|
{ foo: { baz: nil } },
|
166
|
-
foo: { baz: 'Baz' }
|
166
|
+
{ foo: { baz: 'Baz' } }.with_indifferent_access
|
167
167
|
)
|
168
168
|
|
169
169
|
schema do
|
@@ -175,12 +175,12 @@ module Schemacop
|
|
175
175
|
|
176
176
|
assert_cast(
|
177
177
|
{ foo: { bar: '1990-01-13' } },
|
178
|
-
foo: { bar: Date.new(1990, 1, 13) }
|
178
|
+
{ foo: { bar: Date.new(1990, 1, 13) } }.with_indifferent_access
|
179
179
|
)
|
180
180
|
|
181
181
|
assert_cast(
|
182
182
|
{ foo: { bar: '1990-01-13T10:00:00Z' } },
|
183
|
-
foo: { bar: DateTime.new(1990, 1, 13, 10, 0, 0) }
|
183
|
+
{ foo: { bar: DateTime.new(1990, 1, 13, 10, 0, 0) } }.with_indifferent_access
|
184
184
|
)
|
185
185
|
end
|
186
186
|
|
@@ -446,8 +446,8 @@ module Schemacop
|
|
446
446
|
end
|
447
447
|
|
448
448
|
assert_cast(['foo', 42], ['foo', 42])
|
449
|
-
assert_cast(['foo', 42, { foo: '1990-01-01' }], ['foo', 42, { foo: Date.new(1990, 1, 1) }])
|
450
|
-
assert_cast(['foo', 42, { foo: '1990-01-01', bar: :baz }], ['foo', 42, { foo: Date.new(1990, 1, 1), bar: :baz }])
|
449
|
+
assert_cast(['foo', 42, { foo: '1990-01-01' }], ['foo', 42, { foo: Date.new(1990, 1, 1) }.with_indifferent_access])
|
450
|
+
assert_cast(['foo', 42, { foo: '1990-01-01', bar: :baz }], ['foo', 42, { foo: Date.new(1990, 1, 1), bar: :baz }.with_indifferent_access])
|
451
451
|
end
|
452
452
|
|
453
453
|
def test_multiple_add_in_schema
|
@@ -537,7 +537,7 @@ module Schemacop
|
|
537
537
|
additionalItems: false
|
538
538
|
)
|
539
539
|
|
540
|
-
assert_cast [{}], [{ name: 'John' }]
|
540
|
+
assert_cast [{}], [{ name: 'John' }.with_indifferent_access]
|
541
541
|
end
|
542
542
|
|
543
543
|
def test_enum_schema
|
@@ -800,6 +800,16 @@ module Schemacop
|
|
800
800
|
|
801
801
|
assert_cast(%w[foo 1990-01-01], ['foo', Date.new(1990, 1, 1)])
|
802
802
|
end
|
803
|
+
|
804
|
+
def test_contains_multiple_should_fail
|
805
|
+
assert_raises_with_message Exceptions::InvalidSchemaError, 'You can only use "cont" once.' do
|
806
|
+
schema :array do
|
807
|
+
list :string
|
808
|
+
cont :string
|
809
|
+
cont :integer
|
810
|
+
end
|
811
|
+
end
|
812
|
+
end
|
803
813
|
end
|
804
814
|
end
|
805
815
|
end
|
@@ -54,6 +54,14 @@ module Schemacop
|
|
54
54
|
type: :object,
|
55
55
|
additionalProperties: { type: :string }
|
56
56
|
)
|
57
|
+
|
58
|
+
assert_nothing_raised do
|
59
|
+
@schema.validate!({ foo: 'foo' })
|
60
|
+
end
|
61
|
+
|
62
|
+
assert_raises_with_message Exceptions::ValidationError, '/bar: Invalid type, expected "string".' do
|
63
|
+
@schema.validate!({ foo: 'foo', bar: :baz })
|
64
|
+
end
|
57
65
|
end
|
58
66
|
|
59
67
|
def test_property_names
|
@@ -72,8 +80,8 @@ module Schemacop
|
|
72
80
|
propertyNames: '^[a-zA-Z0-9]+$'
|
73
81
|
)
|
74
82
|
|
75
|
-
assert_cast({ foo: 123 }, { foo: 123 })
|
76
|
-
assert_cast({ Foo: 123 }, { Foo: 123 })
|
83
|
+
assert_cast({ foo: 123 }, { foo: 123 }.with_indifferent_access)
|
84
|
+
assert_cast({ Foo: 123 }, { Foo: 123 }.with_indifferent_access)
|
77
85
|
|
78
86
|
# New schema
|
79
87
|
schema :hash, additional_properties: true, property_names: '^[a-z]+$'
|
@@ -82,13 +90,13 @@ module Schemacop
|
|
82
90
|
assert_validation(foo: :bar)
|
83
91
|
assert_validation('foo' => 'bar')
|
84
92
|
assert_validation(Foo: :bar) do
|
85
|
-
error '/', 'Property name
|
93
|
+
error '/', 'Property name "Foo" does not match "^[a-z]+$".'
|
86
94
|
end
|
87
95
|
assert_validation('_foo39sjfdoi 345893(%' => 'bar', 'foo' => 'bar') do
|
88
96
|
error '/', 'Property name "_foo39sjfdoi 345893(%" does not match "^[a-z]+$".'
|
89
97
|
end
|
90
98
|
|
91
|
-
assert_cast({ foo: 123 }, { foo: 123 })
|
99
|
+
assert_cast({ foo: 123 }, { foo: 123 }.with_indifferent_access)
|
92
100
|
end
|
93
101
|
|
94
102
|
def test_required
|
@@ -293,9 +301,9 @@ module Schemacop
|
|
293
301
|
assert_validation({ id_foo: 1, id_bar: 2 })
|
294
302
|
assert_validation({ id_foo: 1, id_bar: 2, value: 4 })
|
295
303
|
|
296
|
-
assert_cast({ id_foo: 1 }, { id_foo: 1 })
|
297
|
-
assert_cast({ id_foo: 1, id_bar: 2 }, { id_foo: 1, id_bar: 2 })
|
298
|
-
assert_cast({ id_foo: 1, id_bar: 2, value: 4 }, { id_foo: 1, id_bar: 2, value: 4 })
|
304
|
+
assert_cast({ id_foo: 1 }, { id_foo: 1 }.with_indifferent_access)
|
305
|
+
assert_cast({ id_foo: 1, id_bar: 2 }, { id_foo: 1, id_bar: 2 }.with_indifferent_access)
|
306
|
+
assert_cast({ id_foo: 1, id_bar: 2, value: 4 }, { id_foo: 1, id_bar: 2, value: 4 }.with_indifferent_access)
|
299
307
|
end
|
300
308
|
|
301
309
|
def test_defaults
|
@@ -311,7 +319,9 @@ module Schemacop
|
|
311
319
|
data = { last_name: 'Doeringer', active: 'true' }
|
312
320
|
data_was = data.dup
|
313
321
|
|
314
|
-
|
322
|
+
expected_data = { first_name: 'John', last_name: 'Doeringer', active: true, address: { street: 'Example 42' } }.with_indifferent_access
|
323
|
+
|
324
|
+
assert_equal(expected_data, @schema.validate(data).data)
|
315
325
|
assert_equal data_was, data
|
316
326
|
|
317
327
|
schema do
|
@@ -526,7 +536,7 @@ module Schemacop
|
|
526
536
|
|
527
537
|
assert_validation(nil)
|
528
538
|
assert_validation(foo: '1')
|
529
|
-
assert_cast({ foo: '1' }, { foo: 1 })
|
539
|
+
assert_cast({ foo: '1' }, { foo: 1 }.with_indifferent_access)
|
530
540
|
|
531
541
|
assert_validation(foo: '1', bar: '2') do
|
532
542
|
error '/', 'Obsolete property "bar".'
|
@@ -552,11 +562,11 @@ module Schemacop
|
|
552
562
|
|
553
563
|
assert_validation(nil)
|
554
564
|
assert_validation(foo: '1')
|
555
|
-
assert_cast({ foo: '1' }, { foo: 1 })
|
565
|
+
assert_cast({ foo: '1' }, { foo: 1 }.with_indifferent_access)
|
556
566
|
|
557
567
|
assert_validation(foo: '1', bar: nil)
|
558
568
|
assert_validation(foo: '1', bar: '2')
|
559
|
-
assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: '2' })
|
569
|
+
assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: '2' }.with_indifferent_access)
|
560
570
|
|
561
571
|
assert_json(
|
562
572
|
type: 'object',
|
@@ -589,11 +599,11 @@ module Schemacop
|
|
589
599
|
|
590
600
|
assert_validation(nil)
|
591
601
|
assert_validation(foo: '1')
|
592
|
-
assert_cast({ foo: '1' }, { foo: 1 })
|
602
|
+
assert_cast({ foo: '1' }, { foo: 1 }.with_indifferent_access)
|
593
603
|
|
594
604
|
assert_validation(foo: '1', bar: nil)
|
595
605
|
assert_validation(foo: '1', bar: '2')
|
596
|
-
assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: '2' })
|
606
|
+
assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: '2' }.with_indifferent_access)
|
597
607
|
|
598
608
|
assert_json(
|
599
609
|
type: 'object',
|
@@ -616,11 +626,11 @@ module Schemacop
|
|
616
626
|
|
617
627
|
assert_validation(nil)
|
618
628
|
assert_validation(foo: '1')
|
619
|
-
assert_cast({ foo: '1' }, { foo: 1 })
|
629
|
+
assert_cast({ foo: '1' }, { foo: 1 }.with_indifferent_access)
|
620
630
|
|
621
631
|
assert_validation(foo: '1', bar: nil)
|
622
632
|
assert_validation(foo: '1', bar: '2')
|
623
|
-
assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: 2 })
|
633
|
+
assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: 2 }.with_indifferent_access)
|
624
634
|
end
|
625
635
|
|
626
636
|
def test_cast_with_additional_any_of
|
@@ -634,7 +644,7 @@ module Schemacop
|
|
634
644
|
|
635
645
|
assert_validation(nil)
|
636
646
|
assert_validation(foo: '1')
|
637
|
-
assert_cast({ foo: '1' }, { foo: 1 })
|
647
|
+
assert_cast({ foo: '1' }, { foo: 1 }.with_indifferent_access)
|
638
648
|
|
639
649
|
assert_validation(foo: '1', bar: nil)
|
640
650
|
assert_validation(foo: '1', bar: '2')
|
@@ -643,7 +653,7 @@ module Schemacop
|
|
643
653
|
error '/qux', 'Does not match any anyOf condition.'
|
644
654
|
end
|
645
655
|
|
646
|
-
assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: '2' })
|
656
|
+
assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: '2' }.with_indifferent_access)
|
647
657
|
|
648
658
|
assert_json(
|
649
659
|
type: 'object',
|
@@ -675,7 +685,7 @@ module Schemacop
|
|
675
685
|
|
676
686
|
assert_validation(nil)
|
677
687
|
assert_validation(foo: '1')
|
678
|
-
assert_cast({ foo: '1' }, { foo: 1 })
|
688
|
+
assert_cast({ foo: '1' }, { foo: 1 }.with_indifferent_access)
|
679
689
|
|
680
690
|
assert_validation(foo: '1', bar: nil)
|
681
691
|
assert_validation(foo: '1', bar: '2')
|
@@ -684,8 +694,8 @@ module Schemacop
|
|
684
694
|
error '/qux', 'Does not match any anyOf condition.'
|
685
695
|
end
|
686
696
|
|
687
|
-
assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: 2 })
|
688
|
-
assert_cast({ foo: '1', bar: '2', qux: '2020-01-13', asd: 1 }, { foo: 1, bar: 2, qux: Date.new(2020, 1, 13), asd: 1 })
|
697
|
+
assert_cast({ foo: '1', bar: '2' }, { foo: 1, bar: 2 }.with_indifferent_access)
|
698
|
+
assert_cast({ foo: '1', bar: '2', qux: '2020-01-13', asd: 1 }, { foo: 1, bar: 2, qux: Date.new(2020, 1, 13), asd: 1 }.with_indifferent_access)
|
689
699
|
|
690
700
|
assert_json(
|
691
701
|
type: 'object',
|
@@ -821,6 +831,54 @@ module Schemacop
|
|
821
831
|
end
|
822
832
|
end
|
823
833
|
end
|
834
|
+
|
835
|
+
def test_schema_with_string_keys
|
836
|
+
schema :hash do
|
837
|
+
int! 'foo'
|
838
|
+
end
|
839
|
+
|
840
|
+
assert_validation(nil)
|
841
|
+
assert_validation({ 'foo' => 42 })
|
842
|
+
assert_validation({ foo: 42 })
|
843
|
+
|
844
|
+
assert_cast({ 'foo' => 42 }, { 'foo' => 42 })
|
845
|
+
assert_cast({ foo: 42 }, { foo: 42 }.with_indifferent_access)
|
846
|
+
|
847
|
+
assert_validation({}) do
|
848
|
+
error '/foo', 'Value must be given.'
|
849
|
+
end
|
850
|
+
|
851
|
+
assert_validation({ :foo => 42, 'foo' => 43 }) do
|
852
|
+
error '/', 'Has 1 ambiguous properties: [:foo].'
|
853
|
+
end
|
854
|
+
end
|
855
|
+
|
856
|
+
def test_schema_with_string_keys_in_data
|
857
|
+
schema :hash do
|
858
|
+
int! :foo
|
859
|
+
end
|
860
|
+
|
861
|
+
assert_validation(nil)
|
862
|
+
assert_validation({ 'foo' => 42 })
|
863
|
+
assert_validation({ foo: 42 })
|
864
|
+
|
865
|
+
assert_cast({ 'foo' => 42 }, { 'foo' => 42 })
|
866
|
+
assert_cast({ foo: 42 }, { foo: 42 }.with_indifferent_access)
|
867
|
+
|
868
|
+
assert_validation({}) do
|
869
|
+
error '/foo', 'Value must be given.'
|
870
|
+
end
|
871
|
+
|
872
|
+
assert_validation({ :foo => 42, 'foo' => 43 }) do
|
873
|
+
error '/', 'Has 1 ambiguous properties: [:foo].'
|
874
|
+
end
|
875
|
+
end
|
876
|
+
|
877
|
+
# def test_invalid_key_names
|
878
|
+
# schema :hash do
|
879
|
+
# int!
|
880
|
+
# end
|
881
|
+
# end
|
824
882
|
end
|
825
883
|
end
|
826
884
|
end
|
@@ -102,11 +102,11 @@ module Schemacop
|
|
102
102
|
|
103
103
|
assert_cast(
|
104
104
|
{ created_at: '2020-01-01' },
|
105
|
-
created_at: Date.new(2020, 1, 1)
|
105
|
+
{ created_at: Date.new(2020, 1, 1) }.with_indifferent_access
|
106
106
|
)
|
107
107
|
assert_cast(
|
108
108
|
{ created_at: '2020-01-01T17:38:20' },
|
109
|
-
created_at: DateTime.new(2020, 1, 1, 17, 38, 20)
|
109
|
+
{ created_at: DateTime.new(2020, 1, 1, 17, 38, 20) }.with_indifferent_access
|
110
110
|
)
|
111
111
|
end
|
112
112
|
|
@@ -127,12 +127,12 @@ module Schemacop
|
|
127
127
|
|
128
128
|
assert_cast(
|
129
129
|
{ foo: { bar: nil } },
|
130
|
-
foo: { bar: nil }
|
130
|
+
{ foo: { bar: nil } }.with_indifferent_access
|
131
131
|
)
|
132
132
|
|
133
133
|
assert_cast(
|
134
134
|
{ foo: { baz: nil } },
|
135
|
-
foo: { baz: 'Baz' }
|
135
|
+
{ foo: { baz: 'Baz' } }.with_indifferent_access
|
136
136
|
)
|
137
137
|
|
138
138
|
schema do
|
@@ -144,12 +144,12 @@ module Schemacop
|
|
144
144
|
|
145
145
|
assert_cast(
|
146
146
|
{ foo: { bar: '1990-01-13' } },
|
147
|
-
foo: { bar: Date.new(1990, 1, 13) }
|
147
|
+
{ foo: { bar: Date.new(1990, 1, 13) } }.with_indifferent_access
|
148
148
|
)
|
149
149
|
|
150
150
|
assert_cast(
|
151
151
|
{ foo: { bar: '1990-01-13T10:00:00Z' } },
|
152
|
-
foo: { bar: DateTime.new(1990, 1, 13, 10, 0, 0) }
|
152
|
+
{ foo: { bar: DateTime.new(1990, 1, 13, 10, 0, 0) } }.with_indifferent_access
|
153
153
|
)
|
154
154
|
end
|
155
155
|
|
@@ -333,7 +333,7 @@ module Schemacop
|
|
333
333
|
ref? :person, :Person, default: {}
|
334
334
|
end
|
335
335
|
|
336
|
-
assert_cast({}, person: { foo: 'bar' })
|
336
|
+
assert_cast({}, { person: { foo: 'bar' } }.with_indifferent_access)
|
337
337
|
end
|
338
338
|
|
339
339
|
def test_casting
|
@@ -344,7 +344,7 @@ module Schemacop
|
|
344
344
|
ref? :person, :Person, default: {}
|
345
345
|
end
|
346
346
|
|
347
|
-
assert_cast({ person: { born_at: '1990-01-13' } }, person: { born_at: Date.new(1990, 1, 13) })
|
347
|
+
assert_cast({ person: { born_at: '1990-01-13' } }, { person: { born_at: Date.new(1990, 1, 13) } }.with_indifferent_access)
|
348
348
|
end
|
349
349
|
end
|
350
350
|
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.0.
|
4
|
+
version: 3.0.0.rc2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sitrox
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-01-
|
11
|
+
date: 2021-01-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|