jschematic 0.0.2 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +1 -1
- data/History.txt +6 -0
- data/README.md +12 -8
- data/features/format.feature +34 -0
- data/features/id.feature +6 -11
- data/features/ref.feature +138 -0
- data/features/step_definitions/jschematic_steps.rb +26 -13
- data/jschematic.gemspec +1 -1
- data/lib/jschematic/attributes/format.rb +43 -19
- data/lib/jschematic/attributes/ref.rb +20 -0
- data/lib/jschematic/attributes.rb +3 -1
- data/lib/jschematic/context.rb +13 -0
- data/lib/jschematic/element.rb +10 -1
- data/lib/jschematic/{validation_error.rb → exceptions.rb} +12 -0
- data/lib/jschematic/schema.rb +22 -9
- data/lib/jschematic.rb +5 -5
- data/spec/jschematic/attributes/enum_spec.rb +30 -0
- data/spec/jschematic/attributes/format_spec.rb +13 -0
- data/spec/jschematic/attributes/ref_spec.rb +15 -0
- data/spec/jschematic/attributes_spec.rb +5 -0
- data/spec/jschematic/schema_spec.rb +7 -20
- data/spec/spec_helper.rb +17 -0
- metadata +13 -5
data/Gemfile.lock
CHANGED
data/History.txt
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
== 0.0.5
|
2
|
+
* Initial support for validation contexts (Mike Sassak)
|
3
|
+
* $ref support (Mike Sassak)
|
4
|
+
* Basic DateTime, Date support (Mike Sassak)
|
5
|
+
* Separate IPv4 and IPv6 classes (Mike Sassak)
|
6
|
+
|
1
7
|
== 0.0.2
|
2
8
|
* Refactored Properties and PatternProperties so the latter inherits from the former (Mike Sassak)
|
3
9
|
* Simple IPv4 CIDR format support (Mike Sassak)
|
data/README.md
CHANGED
@@ -2,24 +2,23 @@
|
|
2
2
|
|
3
3
|
Jschematic is a JSON Schema v3 Validator for Ruby.
|
4
4
|
|
5
|
-
It is currently
|
5
|
+
It is currently pre-release software. The basics work fairly well, but
|
6
|
+
it is a work in progress.
|
6
7
|
|
7
|
-
|
8
|
-
with these exceptions:
|
8
|
+
Most of the core schema definition is supported with these exceptions:
|
9
9
|
|
10
|
-
* $ref
|
11
10
|
* $schema
|
12
11
|
* extends
|
13
12
|
* divisibleBy
|
14
13
|
* disallow
|
15
14
|
|
16
|
-
In addition to this, only IPv4, IPv6 and URI formats are currently
|
15
|
+
In addition to this, only DateTime, Date, IPv4, IPv6 and URI formats are currently
|
17
16
|
implemented.
|
18
17
|
|
19
|
-
Please report any bugs you find
|
20
|
-
|
18
|
+
Please report any bugs you find in the issue tracker here:
|
19
|
+
https://github.com/msassak/jschematic/issues.
|
21
20
|
|
22
|
-
## Usage
|
21
|
+
## Basic Usage
|
23
22
|
|
24
23
|
require 'jschematic'
|
25
24
|
Jschematic.validate(json, schema) # => true or false
|
@@ -30,6 +29,10 @@ tracker here: https://github.com/msassak/jschematic/issues.
|
|
30
29
|
Jschematic doesn't care how you turn JSON into Ruby (though we use the
|
31
30
|
fine yajl-ruby gem for testing).
|
32
31
|
|
32
|
+
## Advanced Usage
|
33
|
+
|
34
|
+
Hasn't been documented yet.
|
35
|
+
|
33
36
|
## Testing
|
34
37
|
|
35
38
|
$ cucumber
|
@@ -42,6 +45,7 @@ Or `rake` if you want to run both.
|
|
42
45
|
* http://tools.ietf.org/html/draft-zyp-json-schema-03
|
43
46
|
* https://github.com/kriszyp/json-schema
|
44
47
|
* http://tools.ietf.org/html/rfc3986
|
48
|
+
* https://groups.google.com/d/topic/json-schema/lftABvH5KkA/discussion
|
45
49
|
|
46
50
|
## Copyright
|
47
51
|
|
data/features/format.feature
CHANGED
@@ -53,3 +53,37 @@ Feature: Core schema: format
|
|
53
53
|
But these are not valid JSON:
|
54
54
|
| "" |
|
55
55
|
| "127.0.0.1" |
|
56
|
+
|
57
|
+
Scenario: Date-Time
|
58
|
+
When the schema is:
|
59
|
+
"""
|
60
|
+
{
|
61
|
+
"type": "string",
|
62
|
+
"format": "date-time"
|
63
|
+
}
|
64
|
+
"""
|
65
|
+
Then these are valid JSON:
|
66
|
+
| "1999-12-31T23:59:59Z" |
|
67
|
+
| "2011-02-27T10:12:13Z" |
|
68
|
+
| "1980-02-29T08:51:32Z" |
|
69
|
+
But these are not valid JSON:
|
70
|
+
| "1999-12-31" |
|
71
|
+
| "1981-02-29T01:01:01Z" |
|
72
|
+
| "August 1st, 1986" |
|
73
|
+
|
74
|
+
Scenario: Date
|
75
|
+
When the schema is:
|
76
|
+
"""
|
77
|
+
{
|
78
|
+
"type": "string",
|
79
|
+
"format": "date"
|
80
|
+
}
|
81
|
+
"""
|
82
|
+
Then these are valid JSON:
|
83
|
+
| "1999-12-31" |
|
84
|
+
| "2011-02-27" |
|
85
|
+
| "1980-02-29" |
|
86
|
+
But these are not valid JSON:
|
87
|
+
| "1981-02-29" |
|
88
|
+
| "August 1st, 1986" |
|
89
|
+
|
data/features/id.feature
CHANGED
@@ -1,4 +1,10 @@
|
|
1
1
|
Feature: Core schema: id
|
2
|
+
|
3
|
+
See: https://groups.google.com/d/msg/json-schema/lftABvH5KkA/KW93ZX-JdpsJ
|
4
|
+
for an explanation. The relevant part is "URIs, not URLs", i.e. id attributes
|
5
|
+
are for *identifying* schemas, not for *locating* them. No retrieval is
|
6
|
+
necessary.
|
7
|
+
|
2
8
|
Scenario: absolute URI, single schema
|
3
9
|
When the schema is:
|
4
10
|
"""
|
@@ -10,17 +16,6 @@ Feature: Core schema: id
|
|
10
16
|
Then the id of "Test Schema" is "http://www.example.com/schemas/json"
|
11
17
|
|
12
18
|
Scenario: relative URI, single schema
|
13
|
-
I-D says: "If this schema is not contained in any parent schema, the
|
14
|
-
current URI of the parent schema is held to be the URI under which
|
15
|
-
this schema was addressed."
|
16
|
-
|
17
|
-
I think this means that the id of the root schema is taken to be the
|
18
|
-
URI from which the schema was retrieved, i.e. schema validators are
|
19
|
-
supposed to include an HTTP client, which seems a bit bonkers to me,
|
20
|
-
or the client passes in the URI from where the schema was retrieved,
|
21
|
-
which is weird, but more palatable. The current implementation does
|
22
|
-
neither of these, but I don't think it's too important at this point.
|
23
|
-
|
24
19
|
When the schema is:
|
25
20
|
"""
|
26
21
|
{
|
@@ -0,0 +1,138 @@
|
|
1
|
+
Feature: Core schema: $ref
|
2
|
+
Scenario: Ref resolves to the same schema
|
3
|
+
When the schema is:
|
4
|
+
"""
|
5
|
+
{
|
6
|
+
"id": "http://www.example.com/schemas/person",
|
7
|
+
"title": "The Best Person Schema Ever",
|
8
|
+
"properties": {
|
9
|
+
"name": { "type": "string" },
|
10
|
+
"age": { "type": "integer" },
|
11
|
+
"favorite_person": { "$ref": "http://www.example.com/schemas/person" }
|
12
|
+
}
|
13
|
+
}
|
14
|
+
"""
|
15
|
+
Then this is valid JSON:
|
16
|
+
"""
|
17
|
+
{
|
18
|
+
"name": "Felizberto Albi",
|
19
|
+
"age": 24,
|
20
|
+
"favorite_person": {
|
21
|
+
"name": "Lil Wayne Pangles",
|
22
|
+
"age": 52,
|
23
|
+
"favorite_person": {
|
24
|
+
"name": "Birdman Pangles",
|
25
|
+
"age": 71,
|
26
|
+
"favorite_person": {
|
27
|
+
"name": "Best here to be silent",
|
28
|
+
"age": 105
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
"""
|
34
|
+
But this is not valid JSON:
|
35
|
+
"""
|
36
|
+
{
|
37
|
+
"name": "Felizberto Albi",
|
38
|
+
"age": 24,
|
39
|
+
"favorite_person": {
|
40
|
+
"name": "Lil Wayne Pangles",
|
41
|
+
"age": "At least a billion. At least."
|
42
|
+
}
|
43
|
+
}
|
44
|
+
"""
|
45
|
+
|
46
|
+
Scenario: Ref with relative path resolves to the same schema
|
47
|
+
TODO: This scenario shares too much information with the one above it.
|
48
|
+
|
49
|
+
When the schema is:
|
50
|
+
"""
|
51
|
+
{
|
52
|
+
"id": "http://www.example.com/schemas/person",
|
53
|
+
"title": "The Best Person Schema Ever",
|
54
|
+
"properties": {
|
55
|
+
"name": { "type": "string" },
|
56
|
+
"age": { "type": "integer" },
|
57
|
+
"favorite_person": { "$ref": "/schemas/person" }
|
58
|
+
}
|
59
|
+
}
|
60
|
+
"""
|
61
|
+
Then this is valid JSON:
|
62
|
+
"""
|
63
|
+
{
|
64
|
+
"name": "Felizberto Albi",
|
65
|
+
"age": 24,
|
66
|
+
"favorite_person": {
|
67
|
+
"name": "Lil Wayne Pangles",
|
68
|
+
"age": 52,
|
69
|
+
"favorite_person": {
|
70
|
+
"name": "Birdman Pangles",
|
71
|
+
"age": 71,
|
72
|
+
"favorite_person": {
|
73
|
+
"name": "Best here to be silent",
|
74
|
+
"age": 105
|
75
|
+
}
|
76
|
+
}
|
77
|
+
}
|
78
|
+
}
|
79
|
+
"""
|
80
|
+
But this is not valid JSON:
|
81
|
+
"""
|
82
|
+
{
|
83
|
+
"name": "Felizberto Albi",
|
84
|
+
"age": 24,
|
85
|
+
"favorite_person": {
|
86
|
+
"name": "Lil Wayne Pangles",
|
87
|
+
"age": "At least a billion. At least."
|
88
|
+
}
|
89
|
+
}
|
90
|
+
"""
|
91
|
+
|
92
|
+
Scenario: Ref resolves to different schema
|
93
|
+
Given this schema:
|
94
|
+
"""
|
95
|
+
{
|
96
|
+
"id": "http://www.example.com/schemas/person",
|
97
|
+
"title": "The Best Person Schema Ever",
|
98
|
+
"properties": {
|
99
|
+
"name": { "type": "string" },
|
100
|
+
"age": { "type": "integer" }
|
101
|
+
}
|
102
|
+
}
|
103
|
+
"""
|
104
|
+
And this schema:
|
105
|
+
"""
|
106
|
+
{
|
107
|
+
"title": "A Happy Family Much Like All Other Happy Families",
|
108
|
+
"type": "array",
|
109
|
+
"items": {
|
110
|
+
"$ref": "http://www.example.com/schemas/person"
|
111
|
+
}
|
112
|
+
}
|
113
|
+
"""
|
114
|
+
Then this is valid JSON:
|
115
|
+
"""
|
116
|
+
[
|
117
|
+
{
|
118
|
+
"name": "Anna Arkadyevna Karenina",
|
119
|
+
"age": 18
|
120
|
+
},
|
121
|
+
|
122
|
+
{
|
123
|
+
"name": "Count Alexei Kirillovich Vronsky",
|
124
|
+
"age": 25
|
125
|
+
}
|
126
|
+
]
|
127
|
+
"""
|
128
|
+
But this is not valid JSON:
|
129
|
+
"""
|
130
|
+
[
|
131
|
+
{
|
132
|
+
"name": "The Underground Man",
|
133
|
+
"age": "timeless"
|
134
|
+
}
|
135
|
+
]
|
136
|
+
"""
|
137
|
+
|
138
|
+
Scenario: Ref appears before the id it references
|
@@ -1,36 +1,40 @@
|
|
1
|
+
Given "this schema:" do |schema|
|
2
|
+
add_schema(parse(schema))
|
3
|
+
end
|
4
|
+
|
1
5
|
When /^the schema is '(.+)'$/ do |schema|
|
2
|
-
|
6
|
+
add_schema(parse(schema))
|
3
7
|
end
|
4
8
|
|
5
9
|
When "the schema is:" do |schema|
|
6
|
-
|
10
|
+
add_schema(parse(schema))
|
7
11
|
end
|
8
12
|
|
9
13
|
Then /^'(.+)' is valid JSON$/ do |json|
|
10
|
-
assert_valid(parse(json),
|
14
|
+
assert_valid(parse(json), all_schemas)
|
11
15
|
end
|
12
16
|
|
13
17
|
Then /^'(.+)' is not valid JSON$/ do |json|
|
14
|
-
assert_invalid(parse(json),
|
18
|
+
assert_invalid(parse(json), all_schemas)
|
15
19
|
end
|
16
20
|
|
17
21
|
Then "this is valid JSON:" do |json|
|
18
|
-
assert_valid(parse(json),
|
22
|
+
assert_valid(parse(json), all_schemas)
|
19
23
|
end
|
20
24
|
|
21
25
|
Then "this is not valid JSON:" do |json|
|
22
|
-
assert_invalid(parse(json),
|
26
|
+
assert_invalid(parse(json), all_schemas)
|
23
27
|
end
|
24
28
|
|
25
29
|
Then "these are valid JSON:" do |instances|
|
26
30
|
instances.raw.each do |row|
|
27
|
-
assert_valid(parse(row[0]),
|
31
|
+
assert_valid(parse(row[0]), all_schemas)
|
28
32
|
end
|
29
33
|
end
|
30
34
|
|
31
35
|
Then "these are not valid JSON:" do |instances|
|
32
36
|
instances.raw.each do |row|
|
33
|
-
assert_invalid(parse(row[0]),
|
37
|
+
assert_invalid(parse(row[0]), all_schemas)
|
34
38
|
end
|
35
39
|
end
|
36
40
|
|
@@ -46,16 +50,25 @@ module JschematicWorld
|
|
46
50
|
raise "Parsing '#{json}' failed with #{e.to_s}"
|
47
51
|
end
|
48
52
|
|
49
|
-
def assert_valid(json,
|
50
|
-
Jschematic.validate(json,
|
53
|
+
def assert_valid(json, raw_schemas)
|
54
|
+
Jschematic.validate(json, *raw_schemas).should be_true
|
51
55
|
end
|
52
56
|
|
53
|
-
def assert_invalid(json,
|
54
|
-
Jschematic.validate(json,
|
57
|
+
def assert_invalid(json, raw_schemas)
|
58
|
+
Jschematic.validate(json, *raw_schemas).should be_false
|
55
59
|
end
|
56
60
|
|
57
61
|
def build_schema
|
58
|
-
@_schema ||= Jschematic::Schema.new(
|
62
|
+
@_schema ||= Jschematic::Schema.new(all_schemas.first)
|
63
|
+
end
|
64
|
+
|
65
|
+
def add_schema(schema)
|
66
|
+
@_schemas ||= []
|
67
|
+
@_schemas << schema
|
68
|
+
end
|
69
|
+
|
70
|
+
def all_schemas
|
71
|
+
@_schemas ||= []
|
59
72
|
end
|
60
73
|
end
|
61
74
|
|
data/jschematic.gemspec
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
require 'ipaddr'
|
2
2
|
require 'addressable/uri'
|
3
|
+
require 'date'
|
3
4
|
|
4
5
|
module Jschematic
|
5
6
|
module Attributes
|
6
7
|
module Format
|
7
8
|
def self.new(format)
|
8
|
-
|
9
|
-
|
10
|
-
Uri.new
|
11
|
-
when "ip-address", "ipv6"
|
12
|
-
Ip.new(format)
|
13
|
-
when "cidr"
|
14
|
-
Cidr.new(format)
|
15
|
-
else
|
16
|
-
NullFormat.new
|
9
|
+
format_class = format.split(/[^\w\d]/).inject("") do |name, part|
|
10
|
+
name << part.capitalize
|
17
11
|
end
|
12
|
+
|
13
|
+
const_get(format_class).new
|
14
|
+
rescue NameError
|
15
|
+
NullFormat.new(format)
|
18
16
|
end
|
19
17
|
|
20
18
|
class Uri
|
@@ -27,20 +25,21 @@ module Jschematic
|
|
27
25
|
end
|
28
26
|
end
|
29
27
|
|
30
|
-
class
|
28
|
+
class IpAddress
|
31
29
|
include Jschematic::Element
|
32
30
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
when "ipv6"
|
38
|
-
:ipv6?
|
39
|
-
end
|
31
|
+
def accepts?(addr)
|
32
|
+
IPAddr.new(addr).ipv4?
|
33
|
+
rescue ArgumentError
|
34
|
+
false
|
40
35
|
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Ipv6
|
39
|
+
include Jschematic::Element
|
41
40
|
|
42
41
|
def accepts?(addr)
|
43
|
-
IPAddr.new(addr).
|
42
|
+
IPAddr.new(addr).ipv6?
|
44
43
|
rescue ArgumentError
|
45
44
|
false
|
46
45
|
end
|
@@ -52,12 +51,37 @@ module Jschematic
|
|
52
51
|
def accepts?(addr_with_cidr)
|
53
52
|
addr, cidr = addr_with_cidr.split("/")
|
54
53
|
return false unless cidr && (1..32).include?(cidr.to_i)
|
55
|
-
|
54
|
+
IpAddress.new.accepts?(addr)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class DateTime
|
59
|
+
include Jschematic::Element
|
60
|
+
|
61
|
+
def accepts?(date_time)
|
62
|
+
::DateTime.strptime(date_time)
|
63
|
+
rescue ArgumentError
|
64
|
+
false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class Date
|
69
|
+
include Jschematic::Element
|
70
|
+
|
71
|
+
def accepts?(date)
|
72
|
+
::Date.strptime(date)
|
73
|
+
rescue ArgumentError
|
74
|
+
false
|
56
75
|
end
|
57
76
|
end
|
58
77
|
|
59
78
|
class NullFormat
|
60
79
|
include Jschematic::Element
|
80
|
+
attr_reader :format
|
81
|
+
|
82
|
+
def initialize(format)
|
83
|
+
@format = format
|
84
|
+
end
|
61
85
|
|
62
86
|
def accepts?(instance)
|
63
87
|
true
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'addressable/uri'
|
2
|
+
|
3
|
+
require 'jschematic/element'
|
4
|
+
|
5
|
+
module Jschematic
|
6
|
+
module Attributes
|
7
|
+
class Ref
|
8
|
+
include Jschematic::Element
|
9
|
+
|
10
|
+
def initialize(uri)
|
11
|
+
@uri = Addressable::URI.parse(uri)
|
12
|
+
end
|
13
|
+
|
14
|
+
def accepts?(instance)
|
15
|
+
schema = Schema.schema_for(@uri) || raise(SchemaNotFoundError.new(@uri))
|
16
|
+
schema.accepts?(instance)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -18,11 +18,13 @@ require 'jschematic/attributes/min_length'
|
|
18
18
|
require 'jschematic/attributes/max_length'
|
19
19
|
require 'jschematic/attributes/enum'
|
20
20
|
require 'jschematic/attributes/format'
|
21
|
+
require 'jschematic/attributes/ref'
|
21
22
|
|
22
23
|
module Jschematic
|
23
24
|
module Attributes
|
24
25
|
def self.[](name)
|
25
|
-
|
26
|
+
name_without_meta = name.gsub(/^\$/, '')
|
27
|
+
const_get(name_without_meta[0].chr.capitalize + name_without_meta[1..-1])
|
26
28
|
end
|
27
29
|
end
|
28
30
|
end
|
data/lib/jschematic/element.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
require 'jschematic/
|
1
|
+
require 'jschematic/exceptions'
|
2
2
|
|
3
3
|
module Jschematic
|
4
4
|
module Element
|
5
5
|
attr_accessor :parent
|
6
|
+
attr_writer :id
|
6
7
|
|
7
8
|
def required?
|
8
9
|
false
|
@@ -12,6 +13,14 @@ module Jschematic
|
|
12
13
|
nil
|
13
14
|
end
|
14
15
|
|
16
|
+
def id
|
17
|
+
if @parent
|
18
|
+
@parent.id + @id
|
19
|
+
else
|
20
|
+
@id
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
15
24
|
def to_s
|
16
25
|
self.class.to_s
|
17
26
|
end
|
@@ -10,4 +10,16 @@ module Jschematic
|
|
10
10
|
"#{what} expected #{expected} but found #{actual}"
|
11
11
|
end
|
12
12
|
end
|
13
|
+
|
14
|
+
class SchemaNotFoundError < StandardError
|
15
|
+
attr_reader :uri
|
16
|
+
|
17
|
+
def initialize(uri)
|
18
|
+
@uri = uri
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
"Cannot find schema for reference '#{uri}'"
|
23
|
+
end
|
24
|
+
end
|
13
25
|
end
|
data/lib/jschematic/schema.rb
CHANGED
@@ -15,7 +15,26 @@ module Jschematic
|
|
15
15
|
schema
|
16
16
|
end
|
17
17
|
|
18
|
-
|
18
|
+
def self.schema_for(ref)
|
19
|
+
if ref.relative?
|
20
|
+
rel = ref.omit(:scheme, :host, :port)
|
21
|
+
if match = schemas.find{ |ref, _| rel == ref.omit(:scheme, :host, :port) }
|
22
|
+
match[-1]
|
23
|
+
end
|
24
|
+
else
|
25
|
+
schemas[ref]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.add_schema(id, schema)
|
30
|
+
schemas[id] = schema
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.schemas
|
34
|
+
@schemas ||= {}
|
35
|
+
end
|
36
|
+
|
37
|
+
attr_reader :default, :title, :description
|
19
38
|
|
20
39
|
attr_accessor :name
|
21
40
|
attr_writer :parent
|
@@ -28,6 +47,8 @@ module Jschematic
|
|
28
47
|
@description = @raw_schema.delete("description") || ""
|
29
48
|
@id = Addressable::URI.parse(@raw_schema.delete("id") || "")
|
30
49
|
|
50
|
+
self.class.add_schema(@id, self) unless @id.to_s.empty?
|
51
|
+
|
31
52
|
@raw_schema.each_pair do |attribute, value|
|
32
53
|
begin
|
33
54
|
attribute = Attributes[attribute].new(value){ |dep| @raw_schema[dep] }
|
@@ -51,14 +72,6 @@ module Jschematic
|
|
51
72
|
children.any?{ |child| child.required? }
|
52
73
|
end
|
53
74
|
|
54
|
-
def id
|
55
|
-
if @parent
|
56
|
-
@parent.id + @id
|
57
|
-
else
|
58
|
-
@id
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
75
|
private
|
63
76
|
|
64
77
|
def add_default(instance)
|
data/lib/jschematic.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
|
-
require 'jschematic/
|
1
|
+
require 'jschematic/context'
|
2
2
|
|
3
3
|
module Jschematic
|
4
|
-
def self.validate(instance,
|
5
|
-
validate!(instance,
|
4
|
+
def self.validate(instance, *schemas)
|
5
|
+
validate!(instance, *schemas)
|
6
6
|
rescue ValidationError
|
7
7
|
false
|
8
8
|
end
|
9
9
|
|
10
|
-
def self.validate!(instance,
|
11
|
-
|
10
|
+
def self.validate!(instance, *schemas)
|
11
|
+
Context.new(*schemas).validate!(instance)
|
12
12
|
end
|
13
13
|
end
|
@@ -1,5 +1,31 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
+
shared_examples_for "an element" do |args|
|
4
|
+
let(:parent) { double("a parent element") }
|
5
|
+
let(:good) { args[:good] }
|
6
|
+
let(:bad) { args[:bad] }
|
7
|
+
|
8
|
+
it "has a parent" do
|
9
|
+
element.parent = parent
|
10
|
+
element.parent.should === parent
|
11
|
+
end
|
12
|
+
|
13
|
+
it "accepts good instance values" do
|
14
|
+
element.should accept(good)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "does not accept bad instance values" do
|
18
|
+
element.should_not accept(bad)
|
19
|
+
end
|
20
|
+
|
21
|
+
xit "adds errors to its parent" do
|
22
|
+
parent = Parent.new
|
23
|
+
element.parent = parent
|
24
|
+
element.validate(:garbage)
|
25
|
+
parent.errors.should include(some_stuff)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
3
29
|
module Jschematic
|
4
30
|
module Attributes
|
5
31
|
describe Enum do
|
@@ -9,6 +35,10 @@ module Jschematic
|
|
9
35
|
expect { subject.new("this is allowed, right?") }.to raise_error
|
10
36
|
expect { subject.new(["not", "really"]) }.to_not raise_error
|
11
37
|
end
|
38
|
+
|
39
|
+
it_should_behave_like "an element", good: 1, bad: 2 do
|
40
|
+
let(:element) { subject.new([1]) }
|
41
|
+
end
|
12
42
|
end
|
13
43
|
end
|
14
44
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Jschematic
|
4
|
+
module Attributes
|
5
|
+
describe Format do
|
6
|
+
it "returns a NullFormat when the format is not found" do
|
7
|
+
format = Format.new("i-don't-exist")
|
8
|
+
format.should be_an_instance_of(Format::NullFormat)
|
9
|
+
format.format.should == "i-don't-exist"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Jschematic
|
4
|
+
module Attributes
|
5
|
+
describe Ref do
|
6
|
+
describe "#accepts?" do
|
7
|
+
it "fails when the references schema does not exist" do
|
8
|
+
Schema.schemas.should be_empty
|
9
|
+
ref = Ref.new("does_not_exist")
|
10
|
+
expect { ref.accepts?({}) }.to raise_error(Jschematic::SchemaNotFoundError)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -7,6 +7,11 @@ module Jschematic
|
|
7
7
|
Attributes::ExclusiveMaximum.should_receive(:new).with(1, 2)
|
8
8
|
subject["exclusiveMaximum"].new(1, 2)
|
9
9
|
end
|
10
|
+
|
11
|
+
it "strips leading '$'" do
|
12
|
+
Attributes::Ref.should_receive(:new).with("foo")
|
13
|
+
subject["$ref"].new("foo")
|
14
|
+
end
|
10
15
|
end
|
11
16
|
end
|
12
17
|
end
|
@@ -32,27 +32,14 @@ module Jschematic
|
|
32
32
|
description.should == ""
|
33
33
|
end
|
34
34
|
end
|
35
|
-
end
|
36
|
-
|
37
|
-
class Parent
|
38
|
-
attr_reader :id
|
39
|
-
def initialize(opts)
|
40
|
-
@id = opts["id"]
|
41
|
-
@children = []
|
42
|
-
end
|
43
35
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
it "builds its id from its parent" do
|
52
|
-
parent = Parent.new("id" => "http://www.example.com/parent/")
|
53
|
-
schema = Schema.new("id" => "child")
|
54
|
-
parent.add_child(schema)
|
55
|
-
schema.id.should == "http://www.example.com/parent/child"
|
36
|
+
describe "#id" do
|
37
|
+
it "is built from the parent's id" do
|
38
|
+
parent = Parent.new("id" => "http://www.example.com/parent/")
|
39
|
+
schema = Schema.new("id" => "child")
|
40
|
+
parent.add_child(schema)
|
41
|
+
schema.id.should == "http://www.example.com/parent/child"
|
42
|
+
end
|
56
43
|
end
|
57
44
|
end
|
58
45
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -14,3 +14,20 @@ RSpec::Matchers.define :accept do |instance_value|
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
module Jschematic
|
18
|
+
class Parent
|
19
|
+
include Jschematic::Composite
|
20
|
+
|
21
|
+
def initialize(opts)
|
22
|
+
self.id = opts["id"]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Child
|
27
|
+
include Jschematic::Element
|
28
|
+
|
29
|
+
def accepts?(instance)
|
30
|
+
!!instance
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 5
|
9
|
+
version: 0.0.5
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Mike Sassak
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-
|
17
|
+
date: 2011-03-15 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -99,6 +99,7 @@ files:
|
|
99
99
|
- features/pattern.feature
|
100
100
|
- features/pattern_properties.feature
|
101
101
|
- features/properties.feature
|
102
|
+
- features/ref.feature
|
102
103
|
- features/required.feature
|
103
104
|
- features/step_definitions/jschematic_steps.rb
|
104
105
|
- features/support/env.rb
|
@@ -123,18 +124,22 @@ files:
|
|
123
124
|
- lib/jschematic/attributes/pattern.rb
|
124
125
|
- lib/jschematic/attributes/pattern_properties.rb
|
125
126
|
- lib/jschematic/attributes/properties.rb
|
127
|
+
- lib/jschematic/attributes/ref.rb
|
126
128
|
- lib/jschematic/attributes/required.rb
|
127
129
|
- lib/jschematic/attributes/type.rb
|
128
130
|
- lib/jschematic/attributes/unique_items.rb
|
129
131
|
- lib/jschematic/composite.rb
|
132
|
+
- lib/jschematic/context.rb
|
130
133
|
- lib/jschematic/element.rb
|
131
134
|
- lib/jschematic/errors.rb
|
135
|
+
- lib/jschematic/exceptions.rb
|
132
136
|
- lib/jschematic/schema.rb
|
133
|
-
- lib/jschematic/validation_error.rb
|
134
137
|
- spec/jschematic/attributes/enum_spec.rb
|
138
|
+
- spec/jschematic/attributes/format_spec.rb
|
135
139
|
- spec/jschematic/attributes/max_items_spec.rb
|
136
140
|
- spec/jschematic/attributes/min_items_spec.rb
|
137
141
|
- spec/jschematic/attributes/minimum_maximum_spec.rb
|
142
|
+
- spec/jschematic/attributes/ref_spec.rb
|
138
143
|
- spec/jschematic/attributes/required_spec.rb
|
139
144
|
- spec/jschematic/attributes/type_spec.rb
|
140
145
|
- spec/jschematic/attributes_spec.rb
|
@@ -172,7 +177,7 @@ rubyforge_project:
|
|
172
177
|
rubygems_version: 1.3.7
|
173
178
|
signing_key:
|
174
179
|
specification_version: 3
|
175
|
-
summary: jschematic 0.0.
|
180
|
+
summary: jschematic 0.0.5
|
176
181
|
test_files:
|
177
182
|
- features/default.feature
|
178
183
|
- features/dependencies.feature
|
@@ -185,14 +190,17 @@ test_files:
|
|
185
190
|
- features/pattern.feature
|
186
191
|
- features/pattern_properties.feature
|
187
192
|
- features/properties.feature
|
193
|
+
- features/ref.feature
|
188
194
|
- features/required.feature
|
189
195
|
- features/step_definitions/jschematic_steps.rb
|
190
196
|
- features/support/env.rb
|
191
197
|
- features/type.feature
|
192
198
|
- spec/jschematic/attributes/enum_spec.rb
|
199
|
+
- spec/jschematic/attributes/format_spec.rb
|
193
200
|
- spec/jschematic/attributes/max_items_spec.rb
|
194
201
|
- spec/jschematic/attributes/min_items_spec.rb
|
195
202
|
- spec/jschematic/attributes/minimum_maximum_spec.rb
|
203
|
+
- spec/jschematic/attributes/ref_spec.rb
|
196
204
|
- spec/jschematic/attributes/required_spec.rb
|
197
205
|
- spec/jschematic/attributes/type_spec.rb
|
198
206
|
- spec/jschematic/attributes_spec.rb
|