schemacop 1.0.2 → 2.0.0
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 +2 -1
- data/.rubocop.yml +59 -1
- data/CHANGELOG.md +10 -0
- data/README.md +389 -199
- data/Rakefile +2 -0
- data/VERSION +1 -1
- data/doc/Schemacop.html +41 -130
- data/doc/Schemacop/ArrayValidator.html +329 -0
- data/doc/Schemacop/BooleanValidator.html +145 -0
- data/doc/Schemacop/Collector.html +535 -0
- data/doc/Schemacop/Exceptions.html +39 -39
- data/doc/Schemacop/Exceptions/InvalidSchemaError.html +124 -0
- data/doc/Schemacop/Exceptions/ValidationError.html +124 -0
- data/doc/Schemacop/FieldNode.html +409 -0
- data/doc/Schemacop/FloatValidator.html +158 -0
- data/doc/Schemacop/HashValidator.html +263 -0
- data/doc/Schemacop/IntegerValidator.html +158 -0
- data/doc/Schemacop/NilValidator.html +145 -0
- data/doc/Schemacop/Node.html +1426 -0
- data/doc/Schemacop/NodeResolver.html +242 -0
- data/doc/Schemacop/NodeSupportingField.html +590 -0
- data/doc/Schemacop/NodeSupportingType.html +614 -0
- data/doc/Schemacop/NodeWithBlock.html +289 -0
- data/doc/Schemacop/NumberValidator.html +232 -0
- data/doc/Schemacop/ObjectValidator.html +288 -0
- data/doc/Schemacop/RootNode.html +171 -0
- data/doc/Schemacop/Schema.html +697 -0
- data/doc/Schemacop/StringValidator.html +295 -0
- data/doc/ScopedEnv.html +351 -0
- data/doc/_index.html +190 -47
- data/doc/class_list.html +24 -31
- data/doc/css/full_list.css +32 -31
- data/doc/css/style.css +244 -91
- data/doc/file.README.html +428 -232
- data/doc/file_list.html +26 -30
- data/doc/frames.html +7 -16
- data/doc/index.html +428 -232
- data/doc/inheritance.graphml +524 -0
- data/doc/inheritance.pdf +825 -0
- data/doc/js/app.js +106 -77
- data/doc/js/full_list.js +170 -135
- data/doc/method_list.html +494 -38
- data/doc/top-level-namespace.html +36 -36
- data/lib/schemacop.rb +22 -7
- data/lib/schemacop/collector.rb +34 -0
- data/lib/schemacop/exceptions.rb +2 -8
- data/lib/schemacop/field_node.rb +26 -0
- data/lib/schemacop/node.rb +127 -0
- data/lib/schemacop/node_resolver.rb +14 -0
- data/lib/schemacop/node_supporting_field.rb +62 -0
- data/lib/schemacop/node_supporting_type.rb +112 -0
- data/lib/schemacop/node_with_block.rb +16 -0
- data/lib/schemacop/root_node.rb +4 -0
- data/lib/schemacop/schema.rb +61 -0
- data/lib/schemacop/scoped_env.rb +18 -0
- data/lib/schemacop/validator/array_validator.rb +30 -0
- data/lib/schemacop/validator/boolean_validator.rb +5 -0
- data/lib/schemacop/validator/float_validator.rb +5 -0
- data/lib/schemacop/validator/hash_validator.rb +18 -0
- data/lib/schemacop/validator/integer_validator.rb +5 -0
- data/lib/schemacop/validator/nil_validator.rb +5 -0
- data/lib/schemacop/validator/number_validator.rb +19 -0
- data/lib/schemacop/validator/object_validator.rb +21 -0
- data/lib/schemacop/validator/string_validator.rb +37 -0
- data/schemacop.gemspec +7 -5
- data/test/custom_check_test.rb +86 -0
- data/test/custom_if_test.rb +95 -0
- data/test/nil_dis_allow_test.rb +41 -0
- data/test/short_forms_test.rb +316 -0
- data/test/test_helper.rb +6 -0
- data/test/types_test.rb +83 -0
- data/test/validator_array_test.rb +97 -0
- data/test/validator_boolean_test.rb +15 -0
- data/test/validator_float_test.rb +57 -0
- data/test/validator_hash_test.rb +71 -0
- data/test/validator_integer_test.rb +46 -0
- data/test/validator_nil_test.rb +13 -0
- data/test/validator_number_test.rb +60 -0
- data/test/validator_object_test.rb +87 -0
- data/test/validator_string_test.rb +76 -0
- metadata +78 -14
- data/doc/Schemacop/Exceptions/Base.html +0 -127
- data/doc/Schemacop/Exceptions/InvalidSchema.html +0 -141
- data/doc/Schemacop/Exceptions/Validation.html +0 -142
- data/doc/Schemacop/MethodValidation.html +0 -120
- data/doc/Schemacop/MethodValidation/ClassMethods.html +0 -196
- data/doc/Schemacop/Validator.html +0 -254
- data/lib/schemacop/validator.rb +0 -145
- data/test/schemacop_validator_test.rb +0 -257
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 57fd66ee6db934d9c0c2026d2d9dab992d777b01
|
4
|
+
data.tar.gz: 27cda8b63a0962684c0f815145aa5e3fba9f3f6c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9fe380ead2ad62aa1d12171a49e1ca7d3ff3019d3c4839448818e724892e2d611702146cea0f12a5671a04db2ad98345a252da60d5aa8e9412e551112a2eb635
|
7
|
+
data.tar.gz: 3deefe749765e7e662f5878175ec9f1cb3aaebbd892c5d45ba0dd9b044bb6fd12baafd2ee22c13a5dc13e18d226ccd51d214b3830d96d2c15d0efe581c0a40ef
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -1,15 +1,43 @@
|
|
1
1
|
AllCops:
|
2
|
+
TargetRubyVersion: 2.3
|
3
|
+
|
2
4
|
Exclude:
|
3
5
|
- 'local/**/*'
|
4
6
|
- 'vendor/**/*'
|
5
7
|
- 'tmp/**/*'
|
6
|
-
- '
|
8
|
+
- 'target/**/*'
|
9
|
+
- 'log/**/*'
|
10
|
+
- 'db/schema.rb'
|
11
|
+
- 'locale/translations.rb'
|
12
|
+
- 'lib/scratch.rb'
|
7
13
|
|
8
14
|
DisplayCopNames: true
|
9
15
|
|
16
|
+
Style/FrozenStringLiteralComment:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
Style/SignalException:
|
20
|
+
EnforcedStyle: only_fail
|
21
|
+
|
22
|
+
Style/ConditionalAssignment:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
Style/IndentArray:
|
26
|
+
EnforcedStyle: consistent
|
27
|
+
|
10
28
|
Metrics/MethodLength:
|
11
29
|
Enabled: false
|
12
30
|
|
31
|
+
Metrics/ClassLength:
|
32
|
+
Enabled: false
|
33
|
+
|
34
|
+
Metrics/ModuleLength:
|
35
|
+
Enabled: false
|
36
|
+
|
37
|
+
Metrics/ParameterLists:
|
38
|
+
Max: 5
|
39
|
+
CountKeywordArgs: false
|
40
|
+
|
13
41
|
Metrics/AbcSize:
|
14
42
|
Enabled: False
|
15
43
|
|
@@ -22,6 +50,12 @@ Metrics/PerceivedComplexity:
|
|
22
50
|
Metrics/LineLength:
|
23
51
|
Max: 160
|
24
52
|
|
53
|
+
Metrics/BlockNesting:
|
54
|
+
Enabled: false
|
55
|
+
|
56
|
+
Metrics/BlockLength:
|
57
|
+
Enabled: false
|
58
|
+
|
25
59
|
Style/IfUnlessModifier:
|
26
60
|
Enabled: false
|
27
61
|
|
@@ -31,6 +65,9 @@ Style/Documentation:
|
|
31
65
|
Style/RedundantReturn:
|
32
66
|
Enabled: false
|
33
67
|
|
68
|
+
Style/AsciiComments:
|
69
|
+
Enabled: false
|
70
|
+
|
34
71
|
Style/GuardClause:
|
35
72
|
Enabled: false
|
36
73
|
|
@@ -40,3 +77,24 @@ Style/ClassAndModuleChildren:
|
|
40
77
|
SupportedStyles:
|
41
78
|
- nested
|
42
79
|
- compact
|
80
|
+
# Checks the style of children definitions at classes and modules.
|
81
|
+
#
|
82
|
+
# Basically there are two different styles:
|
83
|
+
#
|
84
|
+
# `nested` - have each child on a separate line
|
85
|
+
# class Foo
|
86
|
+
# class Bar
|
87
|
+
# end
|
88
|
+
# end
|
89
|
+
#
|
90
|
+
# `compact` - combine definitions as much as possible
|
91
|
+
# class Foo::Bar
|
92
|
+
# end
|
93
|
+
#
|
94
|
+
# The compact style is only forced, for classes / modules with one child.
|
95
|
+
|
96
|
+
Style/NumericPredicate:
|
97
|
+
Enabled: false
|
98
|
+
|
99
|
+
Style/FormatString:
|
100
|
+
Enabled: false
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
+
<!--
|
3
4
|
## master (unreleased)
|
4
5
|
|
5
6
|
### New features
|
@@ -7,6 +8,15 @@
|
|
7
8
|
### Bug fixes
|
8
9
|
|
9
10
|
### Changes
|
11
|
+
-->
|
12
|
+
|
13
|
+
## 2.0.0 (2017-05-15)
|
14
|
+
|
15
|
+
### Changes
|
16
|
+
|
17
|
+
* Completely rewritten the schema specification, breaking backwards
|
18
|
+
compatibility with version 1.x
|
19
|
+
* Added tons of unit tests
|
10
20
|
|
11
21
|
## 1.0.1 (2016-06-07)
|
12
22
|
|
data/README.md
CHANGED
@@ -1,29 +1,49 @@
|
|
1
1
|
[](https://travis-ci.org/sitrox/schemacop)
|
2
2
|
[](https://badge.fury.io/rb/schemacop)
|
3
3
|
|
4
|
-
|
5
4
|
# Schemacop
|
6
5
|
|
6
|
+
This is the README for Schemacop version 2, which **breaks backwards
|
7
|
+
compatibility** with version 1.
|
8
|
+
|
7
9
|
Schemacop validates ruby structures consisting of nested hashes and arrays
|
8
|
-
against
|
10
|
+
against schema definitions described by a simple DSL.
|
11
|
+
|
12
|
+
Examples:
|
9
13
|
|
10
|
-
|
14
|
+
```ruby
|
15
|
+
schema = Schema.new do
|
16
|
+
req :naming, :hash do
|
17
|
+
opt :first_name, :string
|
18
|
+
req :last_name, :string
|
19
|
+
end
|
20
|
+
opt! :age, :integer, min: 18
|
21
|
+
req? :password do
|
22
|
+
type :string, check: proc { |pw| pw.include?('*') }
|
23
|
+
type :integer
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
schema.validate!(
|
28
|
+
naming: { first_name: 'John',
|
29
|
+
last_name: 'Doe' },
|
30
|
+
age: 34,
|
31
|
+
password: 'my*pass'
|
32
|
+
)
|
33
|
+
```
|
11
34
|
|
12
35
|
```ruby
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
}
|
25
|
-
|
26
|
-
Schemacop.validate!(schema, data)
|
36
|
+
schema2 = Schema.new do
|
37
|
+
req :description,
|
38
|
+
:string,
|
39
|
+
if: proc { |str| str.start_with?('Abstract: ') },
|
40
|
+
max: 35,
|
41
|
+
check: proc { |str| !str.end_with?('.') }
|
42
|
+
req :description, :string, min: 35
|
43
|
+
end
|
44
|
+
|
45
|
+
schema2.validate!(description: 'Abstract: a short description')
|
46
|
+
schema2.validate!(description: 'Since this is no abstract, we expect it to be longer.')
|
27
47
|
```
|
28
48
|
|
29
49
|
## Installation
|
@@ -34,289 +54,459 @@ To install the **Schemacop** gem:
|
|
34
54
|
$ gem install schemacop
|
35
55
|
```
|
36
56
|
|
37
|
-
To install it using `bundler` (recommended for any application), add it
|
38
|
-
|
57
|
+
To install it using `bundler` (recommended for any application), add it to your
|
58
|
+
`Gemfile`:
|
39
59
|
|
40
60
|
```ruby
|
41
61
|
gem 'schemacop'
|
42
62
|
```
|
43
63
|
|
44
|
-
##
|
64
|
+
## Basics
|
45
65
|
|
46
|
-
|
66
|
+
Since there is no explicit typing in Ruby, it can be hard to make sure that a
|
67
|
+
method is recieving exactly the right kind of data it needs. The idea of this
|
68
|
+
gem is to define a schema at boot time that will validate the data being passed
|
69
|
+
around at runtime. Those two steps look as follows:
|
70
|
+
|
71
|
+
At boot time:
|
47
72
|
|
48
73
|
```ruby
|
49
|
-
|
74
|
+
my_schema = Schema.new do
|
75
|
+
# Your specification goes here
|
76
|
+
end
|
50
77
|
```
|
51
78
|
|
52
|
-
|
53
|
-
|
79
|
+
At runtime:
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
my_shema.validate!(
|
83
|
+
# Your data goes here
|
84
|
+
)
|
85
|
+
```
|
54
86
|
|
55
|
-
|
87
|
+
`validate!` will fail if the data given to it does not match what was specified
|
88
|
+
in the schema.
|
56
89
|
|
57
|
-
|
58
|
-
vice-versa. 'Leaf-nodes' can be of any data type, but their internal structure
|
59
|
-
is not validated.
|
90
|
+
### Type lines vs. Field lines
|
60
91
|
|
61
|
-
|
62
|
-
|
92
|
+
Schemacop uses a DSL (domain-specific language) to let you describe your
|
93
|
+
schemas. We distinguish between two kinds of identifiers:
|
63
94
|
|
64
|
-
|
65
|
-
|
95
|
+
- Field Lines: We call a key-value pair (like the contents of a hash) a *field*.
|
96
|
+
A field line typically starts with the keyword `req` (for a required field) or
|
97
|
+
`opt` (for an optional field).
|
66
98
|
|
67
|
-
|
99
|
+
- Type Lines: Those start with the keyword `type` and specify the data type to
|
100
|
+
be accepted with a corresponding symbol (e.g. `:integer` or `:boolean`). You
|
101
|
+
can have multiple Type Lines for a Field Line in order to indicate that the
|
102
|
+
field's value can be of one of the specified types.
|
68
103
|
|
69
|
-
|
70
|
-
|
104
|
+
If you don't use any short forms, a schema definition would be something like
|
105
|
+
this:
|
71
106
|
|
72
107
|
```ruby
|
73
|
-
|
74
|
-
type
|
75
|
-
hash
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
108
|
+
s = Schema.new do
|
109
|
+
type :integer
|
110
|
+
type :hash do
|
111
|
+
req 'name' do
|
112
|
+
type :boolean
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
80
116
|
```
|
81
117
|
|
82
|
-
|
83
|
-
|
118
|
+
The above schema would accept either an integer or a hash with exactly one field
|
119
|
+
with key 'present' of type String and value of type Boolean (either TrueClass or
|
120
|
+
FalseClass).
|
84
121
|
|
85
|
-
|
86
|
-
|
87
|
-
|
122
|
+
We will see Type and Field lines in more detail below.
|
123
|
+
|
124
|
+
### `validate` vs `validate!` vs `valid?`
|
125
|
+
|
126
|
+
The method `validate` will return a `Collector` object that contains all
|
127
|
+
validation errors (if any), whereas `validate!` will accumulate all violations
|
128
|
+
and finally throw an exception describing them.
|
129
|
+
|
130
|
+
For simply querying the validity of some data, use the methods `valid?` or
|
131
|
+
`invalid?`.
|
132
|
+
|
133
|
+
## Schemacop's DSL
|
134
|
+
|
135
|
+
In this section, we will ignore [short forms](#short-forms) and explicitly
|
136
|
+
write out everything.
|
137
|
+
|
138
|
+
Inside the block given at the schema instantiation (`Schema.new do ... end`),
|
139
|
+
the following kinds of method calls are allowed (where the outermost must be a
|
140
|
+
Type Line):
|
88
141
|
|
89
|
-
|
142
|
+
### Type Line
|
143
|
+
|
144
|
+
A Type Line always starts with the identifier `type` and specifies a possible
|
145
|
+
data type for a given field (if inside a Field Line) or the given data structure
|
146
|
+
(if directly below the schema instantiation).
|
147
|
+
|
148
|
+
Type Lines are generally of the form
|
90
149
|
|
91
150
|
```ruby
|
92
|
-
|
93
|
-
type: :hash,
|
94
|
-
hash: {
|
95
|
-
name: {
|
96
|
-
type: :hash,
|
97
|
-
hash: {
|
98
|
-
first_name: { type: :string },
|
99
|
-
last_name: { type: :string }
|
100
|
-
}
|
101
|
-
}
|
102
|
-
}
|
103
|
-
}
|
151
|
+
type :my_type, option_1: value_1, ..., option_n: value_n
|
104
152
|
```
|
105
153
|
|
106
|
-
|
154
|
+
where `:my_type` is a supported symbol (see section [Types](#types) below for
|
155
|
+
supported types).
|
156
|
+
|
157
|
+
#### General options
|
158
|
+
|
159
|
+
Some types support specific options that allow additional checks on the nature
|
160
|
+
of the data (such as the `min` option for type `:number`). The following options
|
161
|
+
are supported by all types:
|
162
|
+
|
163
|
+
##### Option `if`
|
164
|
+
|
165
|
+
This option takes a proc (or a lambda) as value. The proc will be called when
|
166
|
+
checking whether or not the data being analyzed fits a certain type. The data is
|
167
|
+
given to the proc, which has to return either true or false. If it returns true,
|
168
|
+
the type of the given data is considered correct and the data will be validated
|
169
|
+
if further options are given.
|
170
|
+
|
171
|
+
Note that the proc in `if` will only get called if the type (`:my_type` from
|
172
|
+
above) fits the data already. You can use the option `if` in order to say: "Even
|
173
|
+
if the data is of type `:my_type`, I consider it having the wrong type if my
|
174
|
+
proc returns false."
|
175
|
+
|
176
|
+
Consider a scenario in which you want to have the following rule set:
|
177
|
+
|
178
|
+
- Only integers may be given
|
179
|
+
- Odd integers must be no larger than 15
|
180
|
+
- No limitations for even integers
|
107
181
|
|
108
|
-
|
109
|
-
specification of the array's contents uby supplying the key `:array`:
|
182
|
+
The corresponding schema would look as follows:
|
110
183
|
|
111
184
|
```ruby
|
112
|
-
|
113
|
-
type: :
|
114
|
-
|
115
|
-
|
116
|
-
}
|
117
|
-
}
|
185
|
+
Schma.new do
|
186
|
+
type :integer, if: proc { |data| data.odd? }, max: 15
|
187
|
+
type :integer
|
188
|
+
end
|
118
189
|
```
|
119
190
|
|
120
|
-
|
191
|
+
Here, the first type line will only accept odd numbers and the option `max: 15`
|
192
|
+
provided by the `:integer` validator will discard numbers higher than 15.
|
121
193
|
|
122
|
-
|
194
|
+
Since the first line only accepts odd numbers, it doesn't apply for even numbers
|
195
|
+
(due to the proc given to `if` they are considered to be of the wrong type) and
|
196
|
+
control falls through to the second type line accepting any integer.
|
197
|
+
|
198
|
+
##### Option `check`
|
199
|
+
|
200
|
+
This option allows you to perform arbitrary custom checks for a given data type.
|
201
|
+
Just like `if`, `check` takes a proc or lambda as a value, but it runs *after*
|
202
|
+
the type checking, meaning that it only gets executed if the data has the right
|
203
|
+
type and the proc in `if` (if any) has returned true.
|
204
|
+
|
205
|
+
The proc passed to the `check` option is given the data being analyzed. It is to
|
206
|
+
return true if the data passes the custom check. If it returns false, Schemacop
|
207
|
+
considers the data to be invalid.
|
208
|
+
|
209
|
+
The following example illustrates the use of the option `check`: Consider a
|
210
|
+
scenario in which you want the following rule set:
|
211
|
+
|
212
|
+
- Data must be of type String
|
213
|
+
- The string must be longer than 5 characters
|
214
|
+
- The second character must be an 'r'
|
215
|
+
|
216
|
+
The corresponding schema would look as follows:
|
123
217
|
|
124
218
|
```ruby
|
125
|
-
|
126
|
-
type: :
|
127
|
-
|
128
|
-
type: :string
|
129
|
-
}
|
130
|
-
}
|
219
|
+
Schema.new do
|
220
|
+
type :string, min: 5, check: proc { |data| data[1] == 'r'}
|
221
|
+
end
|
131
222
|
```
|
132
223
|
|
133
|
-
|
224
|
+
The above Type Line has type `:string` and two options (`min` and `check`). The
|
225
|
+
option `min` is supported by the `:string` validator (covered later).
|
226
|
+
|
227
|
+
### Field Line
|
228
|
+
|
229
|
+
Inside a Type Line of type `:hash` or `Hash`, you may specify an arbitrary
|
230
|
+
number of field lines (one for each key-value pair you want to be in the hash).
|
231
|
+
|
232
|
+
Field Lines start with one of the following six identifiers: `req`, `req?`,
|
233
|
+
`req!`, `opt`, `opt?` or `opt!`:
|
234
|
+
|
235
|
+
- The suffix `-!` means that the field must not be nil.
|
236
|
+
|
237
|
+
- The suffix `-?` means that the field may be nil.
|
238
|
+
|
239
|
+
- The prefix `req-` denotes a required field (validation fails if the given data
|
240
|
+
hash doesn't define it). `req` is a shorthand notation for `req!` (meaning
|
241
|
+
that by default, a required field cannot be nil).
|
242
|
+
|
243
|
+
- The prefix `opt-` denotes an optional field. `opt` is a shorthand notation for
|
244
|
+
`opt?` (meaning that by default, an optional field may be nil).
|
245
|
+
|
246
|
+
To summarize:
|
247
|
+
|
248
|
+
- `req` or `req!`: required and non-nil
|
249
|
+
- `req?`: required but may be nil
|
250
|
+
- `opt` or `opt?`: optional and may be nil
|
251
|
+
- `opt!`: optional but non-nil
|
252
|
+
|
253
|
+
You then pass a block with a single or multiple Type Lines to the field.
|
254
|
+
|
255
|
+
Example: The following schema defines a hash that has a required non-nil field
|
256
|
+
of type String under the key `:name` (of type Symbol) and an optional but
|
257
|
+
non-nil field of type Integer or Date under the key `:age`.
|
134
258
|
|
135
259
|
```ruby
|
136
|
-
|
260
|
+
Schema.new do
|
261
|
+
type :hash do
|
262
|
+
req :name do
|
263
|
+
type :string
|
264
|
+
end
|
265
|
+
opt! :age do
|
266
|
+
type :integer
|
267
|
+
type :object, classes: Date
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
137
271
|
```
|
138
272
|
|
273
|
+
You might find the notation cumbersome, and you'd be right to say so. Luckily
|
274
|
+
there are plenty of short forms available which we will see below.
|
275
|
+
|
139
276
|
## Types
|
140
277
|
|
141
|
-
|
142
|
-
|
278
|
+
The following types are supported by Schemacop:
|
279
|
+
<!-- TODO: Test the following statement: (you can easily extend them by writing
|
280
|
+
another `your_validator.rb` class under `validator/`): -->
|
281
|
+
|
282
|
+
* `:boolean` accepts a Ruby TrueClass or FalseClass instance.
|
283
|
+
|
284
|
+
* `:integer` accepts a Ruby Integer.
|
285
|
+
|
286
|
+
- supported options: `min`, `max` (lower / upper bound)
|
287
|
+
|
288
|
+
* `:float` accepts a Ruby Float.
|
289
|
+
|
290
|
+
- supported options: `min`, `max` (lower / upper bound)
|
291
|
+
|
292
|
+
* `:number` accepts a Ruby Integer or Float.
|
293
|
+
|
294
|
+
- supported options: `min`, `max` (lower / upper bound)
|
143
295
|
|
144
|
-
|
296
|
+
* `:string` accepts a Ruby String.
|
145
297
|
|
146
|
-
|
147
|
-
{ type: String }
|
148
|
-
```
|
298
|
+
- supported options: `min`, `max` (bounds for string length)
|
149
299
|
|
150
|
-
|
151
|
-
available type aliasses):
|
300
|
+
* `:object` accepts an arbitrary Ruby object (any object if no option is given).
|
152
301
|
|
153
|
-
|
154
|
-
|
155
|
-
|
302
|
+
- supported option: `classes`: Ruby class (or an array of them) that will be
|
303
|
+
the only recognized filters. Unlike other options, this one affects not the
|
304
|
+
validation but the type recognition, meaning that you can have multiple Type
|
305
|
+
Lines with different `classes` option for the same field, each having its
|
306
|
+
own validation (e.g. through the option `check`).
|
156
307
|
|
157
|
-
|
308
|
+
* `:array` accepts a Ruby Array.
|
158
309
|
|
159
|
-
|
160
|
-
{ type: [String, :integer] }
|
161
|
-
```
|
310
|
+
- supported options: `min`, `max` (bounds for array size) and `nil`: TODO
|
162
311
|
|
163
|
-
|
164
|
-
structure matches *one* of the given types.
|
312
|
+
- accepts a block with an arbitrary number of Type Lines.
|
165
313
|
|
166
|
-
|
167
|
-
|
314
|
+
- TODO no lookahead for different arrays, see
|
315
|
+
validator_array_test#test_multiple_arrays
|
168
316
|
|
169
|
-
|
170
|
-
{
|
171
|
-
type: [:array, :hash],
|
172
|
-
array: {
|
173
|
-
type: :string
|
174
|
-
},
|
175
|
-
hash: {
|
176
|
-
first_name: :string
|
177
|
-
}
|
178
|
-
}
|
179
|
-
```
|
317
|
+
* `:hash` accepts a Ruby Hash.
|
180
318
|
|
181
|
-
|
319
|
+
- accepts a block with an arbitrary number of Field Lines.
|
182
320
|
|
183
|
-
|
321
|
+
* `:nil`: accepts a Ruby NilClass instance. If you want to allow `nil` as a
|
322
|
+
value in a field, see above for the usage of the suffixes `-!` and `-?` for
|
323
|
+
Field Lines.
|
184
324
|
|
185
|
-
|
186
|
-
|
187
|
-
(`null`).
|
325
|
+
All types support the options `if` and `check` (see the section about Type Lines
|
326
|
+
above).
|
188
327
|
|
189
|
-
|
328
|
+
## Short forms
|
190
329
|
|
191
|
-
|
330
|
+
For convenience, the following short forms may be used (and combined if
|
331
|
+
possible).
|
192
332
|
|
193
|
-
|
194
|
-
|
333
|
+
### Passing a type to a Field Line or schema
|
334
|
+
|
335
|
+
Instead of adding a Type Line in the block of a Field Line, you can omit `do
|
336
|
+
type ... end` and directly write the type after the key of the field.
|
337
|
+
|
338
|
+
Note that when using this short form, you may not give a block to the Field
|
339
|
+
Line.
|
195
340
|
|
196
341
|
```ruby
|
197
|
-
#
|
198
|
-
|
199
|
-
type: :
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
342
|
+
# Long form
|
343
|
+
req :name do
|
344
|
+
type :string, min: 2, max: 5
|
345
|
+
end
|
346
|
+
|
347
|
+
# Short form
|
348
|
+
req :name, :string, min: 2, max: 5
|
204
349
|
```
|
205
350
|
|
206
|
-
|
351
|
+
This means that the value under the key `:name` of type Symbol must be a String
|
352
|
+
containing 2 to 5 characters.
|
207
353
|
|
208
|
-
|
209
|
-
also be `nil`.
|
354
|
+
The short form also works in the schema instantiation:
|
210
355
|
|
211
356
|
```ruby
|
212
|
-
#
|
213
|
-
|
214
|
-
type: :
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
357
|
+
# Long form
|
358
|
+
Schema.new do
|
359
|
+
type :string, min: 2, max: 5
|
360
|
+
end
|
361
|
+
|
362
|
+
# Short form
|
363
|
+
Schema.new(:string, min: 2, max: 5)
|
219
364
|
```
|
220
365
|
|
221
|
-
|
366
|
+
This means that the data given to the schema must be a String that is between 2
|
367
|
+
and 5 characters long.
|
368
|
+
|
369
|
+
### Passing multiple types at once
|
222
370
|
|
223
|
-
|
371
|
+
You can specify several types at once by putting them in an array.
|
224
372
|
|
225
|
-
|
373
|
+
Note that when using this short form, you may not give any options.
|
226
374
|
|
227
375
|
```ruby
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
376
|
+
# Long form
|
377
|
+
opt! :age do
|
378
|
+
type :string
|
379
|
+
type :integer
|
380
|
+
type :boolean
|
381
|
+
end
|
382
|
+
|
383
|
+
# Short form
|
384
|
+
opt! :age do
|
385
|
+
type [:string, :integer, :boolean]
|
386
|
+
end
|
234
387
|
```
|
235
388
|
|
236
|
-
|
389
|
+
Combined with previous short form:
|
237
390
|
|
238
|
-
|
391
|
+
```ruby
|
392
|
+
opt! :age, [:string, :integer, :boolean]
|
393
|
+
```
|
239
394
|
|
240
|
-
|
241
|
-
additional information, you can just skip passing an extra hash and just pass
|
242
|
-
the type instead.
|
395
|
+
This also works in the schema instantiation:
|
243
396
|
|
244
|
-
|
397
|
+
```ruby
|
398
|
+
Schema.new([:string, :integer, :boolean])
|
399
|
+
```
|
400
|
+
|
401
|
+
This means that the schema will validate any data of type String, Integer,
|
402
|
+
TrueClass or FalseClass.
|
403
|
+
|
404
|
+
### Omitting the Type Line in a Field Line
|
405
|
+
|
406
|
+
If you don't specify the type of a field, it will default to `:object` with no
|
407
|
+
options, meaning that the field will accept any kind of data:
|
245
408
|
|
246
409
|
```ruby
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
410
|
+
# Long form
|
411
|
+
req? :child do
|
412
|
+
type :object
|
413
|
+
end
|
414
|
+
|
415
|
+
# Short form
|
416
|
+
req? :child
|
253
417
|
```
|
254
418
|
|
255
|
-
|
419
|
+
### Omitting the Type Line in schema instantiation
|
420
|
+
|
421
|
+
If you don't give a Type Line to a schema, it will accept data of type Hash.
|
422
|
+
Therefore, if you validate Hashes only, you can omit the Type Line and directly
|
423
|
+
write Field Lines in the schema instantiation:
|
256
424
|
|
257
425
|
```ruby
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
426
|
+
# Long form
|
427
|
+
Schema.new do
|
428
|
+
type :hash do
|
429
|
+
req :name do
|
430
|
+
# ...
|
431
|
+
end
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
# Short form
|
436
|
+
Schema.new do
|
437
|
+
req :name do
|
438
|
+
# ...
|
439
|
+
end
|
440
|
+
end
|
262
441
|
```
|
263
442
|
|
264
|
-
###
|
443
|
+
### Shortform for subtypes
|
265
444
|
|
266
|
-
|
267
|
-
hashe's fields or the array's content types, you can omit the `type` key.
|
445
|
+
In case of nested arrays, you can group all Type Lines to a single one.
|
268
446
|
|
269
|
-
|
447
|
+
Note that any options or block passed to the grouped Type Line will be given to
|
448
|
+
the innermost (last) type.
|
270
449
|
|
271
450
|
```ruby
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
451
|
+
# Long form
|
452
|
+
type :array do
|
453
|
+
type :integer, min: 3
|
454
|
+
end
|
455
|
+
|
456
|
+
# Short form
|
457
|
+
type :array, :integer, min: 3
|
278
458
|
```
|
279
459
|
|
280
|
-
|
460
|
+
A more complex example:
|
461
|
+
|
462
|
+
Long form:
|
281
463
|
|
282
464
|
```ruby
|
283
|
-
|
284
|
-
|
285
|
-
|
465
|
+
Schema.new do
|
466
|
+
type :hash do
|
467
|
+
req 'nutrition' do
|
468
|
+
type :array do
|
469
|
+
type :array do
|
470
|
+
type :hash, check: proc { |h| h.member?(:food) || h.member?(:drink) } do
|
471
|
+
opt! :food do
|
472
|
+
type :object
|
473
|
+
end
|
474
|
+
opt! :drink do
|
475
|
+
type :object
|
476
|
+
end
|
477
|
+
end
|
478
|
+
end
|
479
|
+
end
|
480
|
+
end
|
481
|
+
end
|
482
|
+
end
|
286
483
|
```
|
287
484
|
|
288
|
-
|
485
|
+
Short form (with this short form others from above):
|
289
486
|
|
290
487
|
```ruby
|
291
|
-
|
292
|
-
hash: {
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
groups: { array: :integer },
|
298
|
-
birthday: Date,
|
299
|
-
comment: {
|
300
|
-
type: :string,
|
301
|
-
required: false,
|
302
|
-
null: true
|
303
|
-
},
|
304
|
-
ar_object: User
|
305
|
-
}
|
306
|
-
}
|
307
|
-
},
|
308
|
-
}
|
488
|
+
Schema.new do
|
489
|
+
req 'nutrition', :array, :array, :hash, check: proc { |h| h.member?(:food) || h.member?(:drink) } do
|
490
|
+
opt! :food
|
491
|
+
opt! :drink
|
492
|
+
end
|
493
|
+
end
|
309
494
|
```
|
310
495
|
|
496
|
+
This example accepts a hash with exactly one String key 'nutrition' with value
|
497
|
+
of type Array with children of type Array with children of type Hash in which at
|
498
|
+
least one of the Symbol keys `:food` and `:drink` (with any non-nil value type)
|
499
|
+
is present.
|
500
|
+
|
311
501
|
## Exceptions
|
312
502
|
|
313
503
|
Schemacop will throw one of the following checked exceptions:
|
314
504
|
|
315
|
-
* {Schemacop::Exceptions::
|
505
|
+
* {Schemacop::Exceptions::InvalidSchemaError}
|
316
506
|
|
317
507
|
This exception is thrown when the given schema definition format is invalid.
|
318
508
|
|
319
|
-
* {Schemacop::Exceptions::
|
509
|
+
* {Schemacop::Exceptions::ValidationError}
|
320
510
|
|
321
511
|
This exception is thrown when the given data does not comply with the given
|
322
512
|
schema definition.
|
@@ -336,9 +526,9 @@ Schemacop will throw one of the following checked exceptions:
|
|
336
526
|
## Contributors
|
337
527
|
|
338
528
|
Thanks to [Rubocop](https://github.com/bbatsov/rubocop) for great inspiration
|
339
|
-
concerning their name and the structure of their README file. And special thanks
|
340
|
-
[SubGit](http://www.subgit.com/) for their great open source licensing.
|
529
|
+
concerning their name and the structure of their README file. And special thanks
|
530
|
+
to [SubGit](http://www.subgit.com/) for their great open source licensing.
|
341
531
|
|
342
532
|
## Copyright
|
343
533
|
|
344
|
-
Copyright (c)
|
534
|
+
Copyright (c) 2017 Sitrox. See `LICENSE` for further details.
|