schemacop 0.0.1
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 +7 -0
- data/.gitignore +15 -0
- data/.rubocop.yml +42 -0
- data/.travis.yml +6 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +346 -0
- data/RUBY_VERSION +1 -0
- data/Rakefile +38 -0
- data/VERSION +1 -0
- data/doc/Schemacop.html +208 -0
- data/doc/Schemacop/Exceptions.html +115 -0
- data/doc/Schemacop/Exceptions/Base.html +127 -0
- data/doc/Schemacop/Exceptions/InvalidSchema.html +141 -0
- data/doc/Schemacop/Exceptions/Validation.html +142 -0
- data/doc/Schemacop/Validator.html +254 -0
- data/doc/_index.html +177 -0
- data/doc/class_list.html +58 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +57 -0
- data/doc/css/style.css +339 -0
- data/doc/file.README.html +405 -0
- data/doc/file_list.html +60 -0
- data/doc/frames.html +26 -0
- data/doc/index.html +405 -0
- data/doc/js/app.js +219 -0
- data/doc/js/full_list.js +181 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +69 -0
- data/doc/top-level-namespace.html +112 -0
- data/lib/schemacop.rb +11 -0
- data/lib/schemacop/exceptions.rb +10 -0
- data/lib/schemacop/validator.rb +138 -0
- data/schemacop.gemspec +49 -0
- data/test/schemacop_validator_test.rb +197 -0
- metadata +192 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7ff5d0ab4c17e94b315ae9d4b765f80876dbcdcd
|
4
|
+
data.tar.gz: 21f7ac81ccd77383b15e1b07a6e131d6d8d99bb8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 92f19ccddbc4201eb295e2e8216bb8f6096a92a6a54658f79c0cabc244c7e8c6e9a77ded4941c5147ab3f1d1a644645466d335fadd98bef5c0252a23f64dd897
|
7
|
+
data.tar.gz: 863cc1423683b8eaeed9ae889c0a3a424030bf35b2efbb0a34a41edc14edd29d790e6d59ed6199af6df00d7e86e3d2babfcba3b592d9ae70a13a27c0e8dd4836
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
AllCops:
|
2
|
+
Exclude:
|
3
|
+
- 'local/**/*'
|
4
|
+
- 'vendor/**/*'
|
5
|
+
- 'tmp/**/*'
|
6
|
+
- '*.gemspec'
|
7
|
+
|
8
|
+
DisplayCopNames: true
|
9
|
+
|
10
|
+
Metrics/MethodLength:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
Metrics/AbcSize:
|
14
|
+
Enabled: False
|
15
|
+
|
16
|
+
Metrics/CyclomaticComplexity:
|
17
|
+
Enabled: False
|
18
|
+
|
19
|
+
Metrics/PerceivedComplexity:
|
20
|
+
Enabled: False
|
21
|
+
|
22
|
+
Metrics/LineLength:
|
23
|
+
Max: 160
|
24
|
+
|
25
|
+
Style/IfUnlessModifier:
|
26
|
+
Enabled: false
|
27
|
+
|
28
|
+
Style/Documentation:
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
Style/RedundantReturn:
|
32
|
+
Enabled: false
|
33
|
+
|
34
|
+
Style/GuardClause:
|
35
|
+
Enabled: false
|
36
|
+
|
37
|
+
Style/ClassAndModuleChildren:
|
38
|
+
Enabled: false
|
39
|
+
EnforcedStyle: compact
|
40
|
+
SupportedStyles:
|
41
|
+
- nested
|
42
|
+
- compact
|
data/.travis.yml
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--markup=markdown --readme=README.md --no-private lib/**/*.rb
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Sitrox
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,346 @@
|
|
1
|
+
[](https://travis-ci.org/sitrox/schemacop)
|
2
|
+
|
3
|
+
|
4
|
+
# Schemacop
|
5
|
+
|
6
|
+
Schemacop validates ruby structures consisting of nested hashes and arrays
|
7
|
+
against simple schema definitions.
|
8
|
+
|
9
|
+
Example:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
schema = {
|
13
|
+
type: :hash,
|
14
|
+
hash: {
|
15
|
+
first_name: :string,
|
16
|
+
last_name: :string
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
data = {
|
21
|
+
first_name: 'John',
|
22
|
+
last_name: 'Doe'
|
23
|
+
}
|
24
|
+
|
25
|
+
Schemacop.validate!(schema, data)
|
26
|
+
```
|
27
|
+
|
28
|
+
## Installation
|
29
|
+
|
30
|
+
To install the **Schemacop** gem:
|
31
|
+
|
32
|
+
```sh
|
33
|
+
$ gem install schemacop
|
34
|
+
```
|
35
|
+
|
36
|
+
To install it using `bundler` (recommended for any application), add it
|
37
|
+
to your `Gemfile`:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
gem 'schemacop'
|
41
|
+
```
|
42
|
+
|
43
|
+
## Basic usage
|
44
|
+
|
45
|
+
Schemacop's interface is very simple:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
Schemacop.validate!(schema, data)
|
49
|
+
```
|
50
|
+
|
51
|
+
It will throw an exception if either the schema is wrong or the given data does
|
52
|
+
not comply with the schema. See section *Exceptions* for more information.
|
53
|
+
|
54
|
+
## Defining schemas
|
55
|
+
|
56
|
+
Schemacop can validate recursive structures of arrays nested into hashes and
|
57
|
+
vice-versa. 'Leaf-nodes' can be of any data type, but their internal structure
|
58
|
+
is not validated.
|
59
|
+
|
60
|
+
Schema definitions are always a hash, even if they specify an array. Each level
|
61
|
+
of a definition hash has to define a type.
|
62
|
+
|
63
|
+
You can specify any type, but only the types `:hash` and `:array` allow you to
|
64
|
+
specify a sub structure.
|
65
|
+
|
66
|
+
### Defining hashes
|
67
|
+
|
68
|
+
Once a level is defined as a hash (`type: :hash`), you can provide the key
|
69
|
+
`hash` which in turn specifies the keys contained in that hash:
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
{
|
73
|
+
type: :hash,
|
74
|
+
hash: {
|
75
|
+
first_name: { type: :string },
|
76
|
+
last_name: { type: :string }
|
77
|
+
}
|
78
|
+
}
|
79
|
+
```
|
80
|
+
|
81
|
+
If you don't provide the `:hash` key, the hash won't be validated (other than
|
82
|
+
the verification that it really is a hash):
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
{ type: :hash }
|
86
|
+
```
|
87
|
+
|
88
|
+
Hash definitions can be nested deeply:
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
{
|
92
|
+
type: :hash,
|
93
|
+
hash: {
|
94
|
+
name: {
|
95
|
+
type: :hash,
|
96
|
+
hash: {
|
97
|
+
first_name: { type: :string },
|
98
|
+
last_name: { type: :string }
|
99
|
+
}
|
100
|
+
}
|
101
|
+
}
|
102
|
+
}
|
103
|
+
```
|
104
|
+
|
105
|
+
### Defining arrays
|
106
|
+
|
107
|
+
When you define a level as an array (`type: :array`), you can provide further
|
108
|
+
specification of the array's contents uby supplying the key `:array`:
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
{
|
112
|
+
type: :array,
|
113
|
+
array: {
|
114
|
+
type: :string
|
115
|
+
}
|
116
|
+
}
|
117
|
+
```
|
118
|
+
|
119
|
+
This example would define an array of strings.
|
120
|
+
|
121
|
+
Arrays can nest hashes and vice-versa:
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
{
|
125
|
+
type: :array,
|
126
|
+
array: {
|
127
|
+
type: :string
|
128
|
+
}
|
129
|
+
}
|
130
|
+
```
|
131
|
+
|
132
|
+
If you don't provide the `:array` key, the array contents won't be validated:
|
133
|
+
|
134
|
+
```ruby
|
135
|
+
{ type: :array }
|
136
|
+
```
|
137
|
+
|
138
|
+
## Types
|
139
|
+
|
140
|
+
For each level in your schema, you can specify the type in one of the following
|
141
|
+
manors:
|
142
|
+
|
143
|
+
- A ruby class:
|
144
|
+
|
145
|
+
```ruby
|
146
|
+
{ type: String }
|
147
|
+
```
|
148
|
+
|
149
|
+
- A type alias (see {Schemacop::Validator::TYPE_ALIASES} for a full list of
|
150
|
+
available type aliasses):
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
{ type: :boolean }
|
154
|
+
```
|
155
|
+
|
156
|
+
- A list of ruby classes or type aliases:
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
{ type: [String, :integer] }
|
160
|
+
```
|
161
|
+
|
162
|
+
When specifying more than one type, it is validated that the given data
|
163
|
+
structure matches *one* of the given types.
|
164
|
+
|
165
|
+
If you specify both `:array` and `:hash` in such a type array, you can provide
|
166
|
+
a specification for both `array` and `hash` types:
|
167
|
+
|
168
|
+
```ruby
|
169
|
+
{
|
170
|
+
type: [:array, :hash],
|
171
|
+
array: {
|
172
|
+
type: :string
|
173
|
+
},
|
174
|
+
hash: {
|
175
|
+
first_name: :string
|
176
|
+
}
|
177
|
+
}
|
178
|
+
```
|
179
|
+
|
180
|
+
It will then determine which specification to use based on the actual data.
|
181
|
+
|
182
|
+
## Null and required
|
183
|
+
|
184
|
+
Using the optional parameters `required` and `null`, you can control whether a
|
185
|
+
specific substructure must be provided (`required`) and if it can be `nil`
|
186
|
+
(`null`).
|
187
|
+
|
188
|
+
These two parameters can be combined in any way.
|
189
|
+
|
190
|
+
### Required validation
|
191
|
+
|
192
|
+
When validating with `required = false`, it means that the whole key can be
|
193
|
+
omitted. As an example:
|
194
|
+
|
195
|
+
```ruby
|
196
|
+
# Successfully validates data hash: {}
|
197
|
+
{
|
198
|
+
type: :hash,
|
199
|
+
hash: {
|
200
|
+
first_name: { type: :string, required: false }
|
201
|
+
}
|
202
|
+
}
|
203
|
+
```
|
204
|
+
|
205
|
+
### Null validation
|
206
|
+
|
207
|
+
When validating with `null = true`, the key must still be present, but it can
|
208
|
+
also be `nil`.
|
209
|
+
|
210
|
+
```ruby
|
211
|
+
# Successfully validates data hash: { first_name: nil }
|
212
|
+
{
|
213
|
+
type: :hash,
|
214
|
+
hash: {
|
215
|
+
first_name: { type: :string, null: false }
|
216
|
+
}
|
217
|
+
}
|
218
|
+
```
|
219
|
+
|
220
|
+
## Allowed values
|
221
|
+
|
222
|
+
For any level, you can optionally specify an array of values that are allowed.
|
223
|
+
|
224
|
+
For example:
|
225
|
+
|
226
|
+
```ruby
|
227
|
+
{
|
228
|
+
type: :hash,
|
229
|
+
hash: {
|
230
|
+
category: { type: :integer, allowed_values: [1, 2, 3] }
|
231
|
+
}
|
232
|
+
}
|
233
|
+
```
|
234
|
+
|
235
|
+
## Shortcuts
|
236
|
+
|
237
|
+
### Type shortcut
|
238
|
+
|
239
|
+
If you'd just like to define a type for a level but don't need to supply any
|
240
|
+
additional information, you can just skip passing an extra hash and just pass
|
241
|
+
the type instead.
|
242
|
+
|
243
|
+
For example, the following
|
244
|
+
|
245
|
+
```ruby
|
246
|
+
{
|
247
|
+
type: :array,
|
248
|
+
array: {
|
249
|
+
type: :string
|
250
|
+
}
|
251
|
+
}
|
252
|
+
```
|
253
|
+
|
254
|
+
can also be written as:
|
255
|
+
|
256
|
+
```ruby
|
257
|
+
{
|
258
|
+
type: :array,
|
259
|
+
array: :string
|
260
|
+
}
|
261
|
+
```
|
262
|
+
|
263
|
+
### Quick hash and array
|
264
|
+
|
265
|
+
When specifying a level as hash or array and you're further specifying the
|
266
|
+
hashe's fields or the array's content types, you can omit the `type` key.
|
267
|
+
|
268
|
+
For example, the following
|
269
|
+
|
270
|
+
```ruby
|
271
|
+
{
|
272
|
+
type: :array,
|
273
|
+
array: {
|
274
|
+
type: :string
|
275
|
+
}
|
276
|
+
}
|
277
|
+
```
|
278
|
+
|
279
|
+
can also be written as:
|
280
|
+
|
281
|
+
```ruby
|
282
|
+
{
|
283
|
+
array: :string
|
284
|
+
}
|
285
|
+
```
|
286
|
+
|
287
|
+
## Example schema
|
288
|
+
|
289
|
+
```ruby
|
290
|
+
{
|
291
|
+
hash: {
|
292
|
+
id: [Integer, String],
|
293
|
+
name: :string,
|
294
|
+
meta: {
|
295
|
+
hash: {
|
296
|
+
groups: { array: :integer },
|
297
|
+
birthday: Date,
|
298
|
+
comment: {
|
299
|
+
type: :string,
|
300
|
+
required: false,
|
301
|
+
null: true
|
302
|
+
},
|
303
|
+
ar_object: User
|
304
|
+
}
|
305
|
+
}
|
306
|
+
},
|
307
|
+
}
|
308
|
+
```
|
309
|
+
|
310
|
+
## Exceptions
|
311
|
+
|
312
|
+
Schemacop will throw one of the following checked exceptions:
|
313
|
+
|
314
|
+
* {Schemacop::Exceptions::InvalidSchema}
|
315
|
+
|
316
|
+
This exception is thrown when the given schema definition format is invalid.
|
317
|
+
|
318
|
+
* {Schemacop::Exceptions::Validation}
|
319
|
+
|
320
|
+
This exception is thrown when the given data does not comply with the given
|
321
|
+
schema definition.
|
322
|
+
|
323
|
+
## Known limitations
|
324
|
+
|
325
|
+
* Schemacop does not yet allow cyclic structures with infinite depth.
|
326
|
+
|
327
|
+
* Schemacop aborts when it encounters an error. It is not able to collect a full
|
328
|
+
list of multiple errors.
|
329
|
+
|
330
|
+
* Schemacop is not made for validating complex causalities (i.e. field `a`
|
331
|
+
needs to be given only if field `b` is present).
|
332
|
+
|
333
|
+
* Schemacop does not yet support string regex matching.
|
334
|
+
|
335
|
+
## Contributors
|
336
|
+
|
337
|
+
Thanks to [Rubocop](https://github.com/bbatsov/rubocop) for great inspiration
|
338
|
+
concerning their name and the structure of their README file.
|
339
|
+
|
340
|
+
## Changelog
|
341
|
+
|
342
|
+
Schemacop's changelog is available [here](CHANGELOG.md).
|
343
|
+
|
344
|
+
## Copyright
|
345
|
+
|
346
|
+
Copyright (c) 2016 Sitrox. See [LICENSE](LICENSE) for further details.
|