schemacop 1.0.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Build Status](https://travis-ci.org/sitrox/schemacop.svg?branch=master)](https://travis-ci.org/sitrox/schemacop)
|
2
2
|
[![Gem Version](https://badge.fury.io/rb/schemacop.svg)](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.
|