sexy_json_schemas 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format Fivemat
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sexy_json_schemas.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,9 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch(%r{^lib/(.+)\.rb$}) { "spec" }
6
+ watch(%r{^spec/.+_spec\.rb$})
7
+ #watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
8
+ watch('spec/spec_helper.rb') { "spec" }
9
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Donald Plummer
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # SexyJSONSchemas
2
+
3
+ A DSL for generating JSON Schemas.
4
+
5
+ Based on draft 3 of the [zyp-json-schema](http://tools.ietf.org/id/draft-zyp-json-schema-03.html).
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'sexy_json_schemas'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install sexy_json_schemas
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,18 @@
1
+ module SexyJSONSchemas
2
+ module DSL
3
+ def schema(name, options = {}, &block)
4
+ options[:root_element] ||= name unless options[:root_element] == false
5
+ @schema_name = name
6
+ @definition = SchemaDefinition.new(name, options)
7
+ @definition.instance_eval(&block)
8
+ end
9
+
10
+ def schema_name
11
+ @schema_name
12
+ end
13
+
14
+ def as_json
15
+ @definition.as_json
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ module SexyJSONSchemas
2
+ module Properties
3
+ class AnonymousObject < Properties::Object
4
+ def initialize
5
+ super(nil)
6
+ end
7
+
8
+ def as_json
9
+ @properties.inject({}) do |acc, property|
10
+ acc.merge(property.as_json)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ module SexyJSONSchemas
2
+ module Properties
3
+ class Any < Base
4
+ def type
5
+ "any"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,45 @@
1
+ module SexyJSONSchemas
2
+ module Properties
3
+ class Array < Base
4
+ def self.define_property_delegator(property)
5
+ define_method(property) do |*args|
6
+ blank_object = Properties::AnonymousObject.new
7
+ blank_object.send(property, '', *args)
8
+ @item_schemas << blank_object
9
+ end
10
+ end
11
+
12
+ Properties::Object.property_methods.each do |property|
13
+ define_property_delegator(property)
14
+ end
15
+
16
+ def type
17
+ "array"
18
+ end
19
+
20
+ def initialize(*args, &block)
21
+ super(*args)
22
+ @item_schemas = []
23
+
24
+ instance_eval(&block) if block_given?
25
+ end
26
+
27
+
28
+ def as_json
29
+ super.tap do |json|
30
+ json['items'] = items_json
31
+ end
32
+ end
33
+
34
+ def items_json
35
+ if @item_schemas.length == 0
36
+ {}
37
+ elsif @item_schemas.length == 1
38
+ @item_schemas.first.as_json
39
+ else
40
+ @item_schemas.map(&:as_json)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,40 @@
1
+ module SexyJSONSchemas
2
+ module Properties
3
+ class Base
4
+ attr_reader :name
5
+
6
+ def initialize(name, options = {})
7
+ @name = name
8
+ @options = options
9
+ end
10
+
11
+ def type
12
+ nil
13
+ end
14
+
15
+ def as_json
16
+ json = { }
17
+
18
+ json["type"] = type if type
19
+
20
+ if @options[:required]
21
+ json['required'] = true
22
+ end
23
+
24
+ if @options[:enum]
25
+ json['enum'] = @options[:enum]
26
+ end
27
+
28
+ if @options[:format]
29
+ json['format'] = @options[:format]
30
+ end
31
+
32
+ if @options[:description]
33
+ json['description'] = @options[:description]
34
+ end
35
+
36
+ json
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,9 @@
1
+ module SexyJSONSchemas
2
+ module Properties
3
+ class Boolean < Base
4
+ def type
5
+ "boolean"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module SexyJSONSchemas
2
+ module Properties
3
+ class Integer < Number
4
+ def type
5
+ "integer"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module SexyJSONSchemas
2
+ module Properties
3
+ class Null < Base
4
+ def type
5
+ "null"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ module SexyJSONSchemas
2
+ module Properties
3
+ class Number < Base
4
+ def type
5
+ "number"
6
+ end
7
+
8
+ def as_json
9
+ super.tap do |json|
10
+ if @options[:minimum]
11
+ json['minimum'] = @options[:minimum]
12
+ end
13
+
14
+ if @options[:maximum]
15
+ json['maximum'] = @options[:maximum]
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,83 @@
1
+ module SexyJSONSchemas
2
+ module Properties
3
+ class Object < Base
4
+ def type
5
+ "object"
6
+ end
7
+
8
+ def self.property_methods
9
+ [
10
+ :integer_property,
11
+ :string_property,
12
+ :object_property,
13
+ :number_property,
14
+ :boolean_property,
15
+ :null_property,
16
+ :any_property,
17
+ :union_property,
18
+ :array_property,
19
+ :ref_property
20
+ ]
21
+ end
22
+
23
+ def initialize(name, options = {}, &block)
24
+ super(name, options)
25
+ @properties = []
26
+ instance_eval(&block) if block_given?
27
+ end
28
+
29
+ def as_json
30
+ super.tap do |json|
31
+ json["properties"] = properties
32
+ end
33
+ end
34
+
35
+ def properties
36
+ @properties.inject({}) do |acc, property|
37
+ acc[property.name] = property.as_json
38
+ acc
39
+ end
40
+ end
41
+
42
+ def integer_property(*args, &block)
43
+ @properties << Properties::Integer.new(*args, &block)
44
+ end
45
+
46
+ def number_property(*args, &block)
47
+ @properties << Properties::Number.new(*args, &block)
48
+ end
49
+
50
+ def boolean_property(*args, &block)
51
+ @properties << Properties::Boolean.new(*args, &block)
52
+ end
53
+
54
+ def null_property(*args, &block)
55
+ @properties << Properties::Null.new(*args, &block)
56
+ end
57
+
58
+ def string_property(*args, &block)
59
+ @properties << Properties::String.new(*args, &block)
60
+ end
61
+
62
+ def any_property(*args, &block)
63
+ @properties << Properties::Any.new(*args, &block)
64
+ end
65
+
66
+ def union_property(*args, &block)
67
+ @properties << Properties::Union.new(*args, &block)
68
+ end
69
+
70
+ def array_property(*args, &block)
71
+ @properties << Properties::Array.new(*args, &block)
72
+ end
73
+
74
+ def ref_property(*args, &block)
75
+ @properties << Properties::Ref.new(*args, &block)
76
+ end
77
+
78
+ def object_property(*args, &block)
79
+ @properties << Properties::Object.new(*args, &block)
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,14 @@
1
+ module SexyJSONSchemas
2
+ module Properties
3
+ class Ref < Base
4
+ def initialize(name, schema, options = {})
5
+ super(name, options)
6
+ @schema = schema
7
+ end
8
+
9
+ def as_json
10
+ {"$ref" => @schema}
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ module SexyJSONSchemas
2
+ module Properties
3
+ class String < Base
4
+ def type
5
+ "string"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ module SexyJSONSchemas
2
+ module Properties
3
+ class Union < Base
4
+ def initialize(name, types, *args)
5
+ super(name, *args)
6
+ @types = types
7
+ end
8
+
9
+ def type
10
+ @types.map(&:to_s)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,47 @@
1
+ module SexyJSONSchemas
2
+ class SchemaDefinition
3
+ extend Forwardable
4
+
5
+ attr_reader :name
6
+
7
+ def_delegators :@core_object,
8
+ *Properties::Object.property_methods
9
+
10
+ def initialize(name, options)
11
+ @name = name
12
+ @root_element = options.fetch(:root_element, name)
13
+ @core_object = Properties::Object.new(name, options)
14
+ end
15
+
16
+ def as_json
17
+ json = @core_object.as_json
18
+
19
+ if root_element?
20
+ json = wrap_in_root(json)
21
+ end
22
+
23
+ json['name'] = name
24
+
25
+ json
26
+ end
27
+
28
+ private
29
+
30
+ def properties
31
+ @core_object.as_json
32
+ end
33
+
34
+ def root_element?
35
+ @root_element
36
+ end
37
+
38
+ def wrap_in_root(json)
39
+ {
40
+ "type" => "object",
41
+ "properties" => {
42
+ @root_element => json
43
+ }
44
+ }
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,20 @@
1
+ module SexyJSONSchemas
2
+ def self.included(receiver)
3
+ receiver.extend(DSL)
4
+ end
5
+ end
6
+
7
+ require 'sexy_json_schemas/dsl'
8
+ require 'sexy_json_schemas/properties/base'
9
+ require 'sexy_json_schemas/properties/number'
10
+ require 'sexy_json_schemas/properties/integer'
11
+ require 'sexy_json_schemas/properties/boolean'
12
+ require 'sexy_json_schemas/properties/null'
13
+ require 'sexy_json_schemas/properties/string'
14
+ require 'sexy_json_schemas/properties/any'
15
+ require 'sexy_json_schemas/properties/union'
16
+ require 'sexy_json_schemas/properties/object'
17
+ require 'sexy_json_schemas/properties/anonymous_object'
18
+ require 'sexy_json_schemas/properties/array'
19
+ require 'sexy_json_schemas/properties/ref'
20
+ require 'sexy_json_schemas/schema_definition'
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "sexy_json_schemas"
7
+ gem.version = "0.0.5"
8
+ gem.authors = ["Donald Plummer", "Michael Xavier"]
9
+ gem.email = ["donald@crystalcommerce.com", "xavier@crystalcommerce.com"]
10
+ gem.description = %q{A DSL for generating JSON Schemas}
11
+ gem.summary = %q{A DSL for generating JSON Schemas}
12
+ gem.homepage = "http://github.com/crystalcommerce/sexy_json_schemas"
13
+
14
+ gem.files = `git ls-files`.split($/)
15
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
16
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
17
+ gem.require_paths = ["lib"]
18
+
19
+ gem.add_development_dependency("rake", "~> 0.9.2")
20
+ gem.add_development_dependency("rspec", "~> 2.11.0")
21
+ gem.add_development_dependency("guard", "~> 1.2.1")
22
+ gem.add_development_dependency("guard-rspec", "~> 1.1.0")
23
+ gem.add_development_dependency("fivemat", "~> 1.1.0")
24
+ gem.add_development_dependency("rb-inotify", "~> 0.8.8")
25
+ gem.add_development_dependency("require_relative", "~> 1.0.3") # for json-schema
26
+ gem.add_development_dependency("json-schema", "~> 1.0.9")
27
+ gem.add_development_dependency("json", "~> 1.7.5")
28
+ end
@@ -0,0 +1,137 @@
1
+ {
2
+ "id" : "http://json-schema.org/schema#",
3
+ "type" : ["object","string"],
4
+ "format": "uri",
5
+
6
+ "properties" : {
7
+ "type" : {
8
+ "type" : ["string", "array"],
9
+ "items" : {
10
+ "type" : ["string", "#"]
11
+ },
12
+ "uniqueItems" : true,
13
+ "default" : "any"
14
+ },
15
+
16
+ "properties" : {
17
+ "type" : "object",
18
+ "additionalProperties" : "#",
19
+ "default" : {}
20
+ },
21
+
22
+ "items" : {
23
+ "type" : ["#", "array"],
24
+ "items" : "#",
25
+ "default" : {}
26
+ },
27
+
28
+ "required" : {
29
+ "type" : "boolean",
30
+ "default" : false
31
+ },
32
+
33
+ "additionalProperties" : {
34
+ "type" : ["#", "boolean"],
35
+ "default" : {}
36
+ },
37
+ "additionalItems" : {
38
+ "type" : ["#", "boolean"],
39
+ "default" : {}
40
+ },
41
+
42
+ "requires" : {
43
+ "type" : ["string", "#"]
44
+ },
45
+
46
+ "minimum" : {
47
+ "type" : "number"
48
+ },
49
+
50
+ "maximum" : {
51
+ "type" : "number"
52
+ },
53
+
54
+ "exclusiveMinimum" : {
55
+ "type" : "number"
56
+ },
57
+
58
+ "exclusiveMaximum" : {
59
+ "type" : "number"
60
+ },
61
+
62
+ "minItems" : {
63
+ "type" : "integer",
64
+ "minimum" : 0,
65
+ "default" : 0
66
+ },
67
+
68
+ "maxItems" : {
69
+ "type" : "integer"
70
+ },
71
+
72
+ "uniqueItems" : {
73
+ "type" : "boolean",
74
+ "default" : false
75
+ },
76
+
77
+ "pattern" : {
78
+ "type" : "string",
79
+ "format" : "regex"
80
+ },
81
+
82
+ "minLength" : {
83
+ "type" : "integer",
84
+ "minimum" : 0,
85
+ "default" : 0
86
+ },
87
+
88
+ "maxLength" : {
89
+ "type" : "integer"
90
+ },
91
+
92
+ "enum" : {
93
+ "type" : "array",
94
+ "minItems" : 1,
95
+ "uniqueItems" : true
96
+ },
97
+
98
+ "title" : {
99
+ "type" : "string"
100
+ },
101
+
102
+ "description" : {
103
+ "type" : "string"
104
+ },
105
+
106
+ "format" : {
107
+ "type" : "string"
108
+ },
109
+
110
+ "maxDecimal" : {
111
+ "type" : "number",
112
+ "minimum" : 0
113
+ },
114
+
115
+ "disallow" : {
116
+ "type" : ["string", "array", "#"],
117
+ "items" : {
118
+ "type" : ["string", "#"]
119
+ },
120
+ "uniqueItems" : true
121
+ },
122
+
123
+ "extends" : {
124
+ "type" : ["#", "array"],
125
+ "items" : "#",
126
+ "default" : {}
127
+ }
128
+ },
129
+ "links" : [
130
+ {
131
+ "href" : "{id}",
132
+ "rel" : "self"
133
+ }
134
+ ],
135
+
136
+ "default" : {}
137
+ }
@@ -0,0 +1,26 @@
1
+ require 'rspec/expectations'
2
+ require 'require_relative'
3
+ require 'json-schema'
4
+ require 'json'
5
+
6
+ module JSONValidatorMatchers
7
+ extend RSpec::Matchers::DSL
8
+
9
+ META_SCHEMA = JSON.parse(File.read(File.join(File.dirname(__FILE__),
10
+ 'json_schema.schema')))
11
+
12
+ matcher :be_valid_json_schema do
13
+ match do |generated_schema|
14
+ JSON::Validator.validate(META_SCHEMA, generated_schema)
15
+ end
16
+
17
+ failure_message_for_should do |schema|
18
+ errors = JSON::Validator.fully_validate(META_SCHEMA, schema)
19
+ "expected no validation errors but got:\n #{errors.join("\n ")}"
20
+ end
21
+
22
+ failure_message_for_should_not do |schema|
23
+ "expected validation errors but got none"
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,325 @@
1
+ require 'spec_helper'
2
+
3
+ JSONTestClass = Class.new {
4
+ include SexyJSONSchemas
5
+ }
6
+
7
+ shared_examples_for "valid schema generator" do
8
+ its(:as_json) { should be_valid_json_schema }
9
+ end
10
+
11
+ describe SexyJSONSchemas do
12
+ class Money
13
+ include SexyJSONSchemas
14
+
15
+ schema "money" do
16
+ integer_property "cents", :required => true
17
+ string_property "currency", :description => "ISO currency code"
18
+ end
19
+ end
20
+
21
+ describe Money do
22
+ subject { Money }
23
+
24
+ its(:schema_name) { should == "money" }
25
+ its(:as_json) do
26
+ should == {
27
+ "name" => "money",
28
+ "type" => "object",
29
+ "properties" => {
30
+ "money" => {
31
+ "type" => "object",
32
+ "properties" => {
33
+ "cents" => {
34
+ "type" => "integer",
35
+ "required" => true
36
+ },
37
+ "currency" => {
38
+ "type" => "string",
39
+ "description" => "ISO currency code"
40
+ }
41
+ }
42
+ }
43
+ }
44
+ }
45
+ end
46
+
47
+ it_should_behave_like "valid schema generator"
48
+ end
49
+
50
+ describe "null properties" do
51
+ subject { Class.new(JSONTestClass) {
52
+ schema "void", :root_element => false do
53
+ null_property "nope"
54
+ end
55
+ }}
56
+
57
+ its(:as_json) { should == {
58
+ "name" => "void",
59
+ "type" => "object",
60
+ "properties" => {
61
+ "nope" => {
62
+ "type" => "null"
63
+ }
64
+ }
65
+ }}
66
+
67
+ it_should_behave_like "valid schema generator"
68
+ end
69
+
70
+ describe "string properties" do
71
+ subject { Class.new(JSONTestClass) {
72
+ schema "void", :root_element => false do
73
+ string_property "silly"
74
+ string_property "when", :format => 'date-time'
75
+ end
76
+ }}
77
+
78
+ its(:as_json) { should == {
79
+ "name" => "void",
80
+ "type" => "object",
81
+ "properties" => {
82
+ "silly" => {
83
+ "type" => "string"
84
+ },
85
+ "when" => {
86
+ "format" => "date-time",
87
+ "type" => "string"
88
+ }
89
+ }
90
+ }}
91
+
92
+ it_should_behave_like "valid schema generator"
93
+ end
94
+
95
+ describe "number properties" do
96
+ subject { Class.new(JSONTestClass) {
97
+ schema "void", :root_element => false do
98
+ number_property "beast", :minimum => 0,
99
+ :maximum => 100
100
+ end
101
+ }}
102
+
103
+ its(:as_json) { should == {
104
+ "name" => "void",
105
+ "type" => "object",
106
+ "properties" => {
107
+ "beast" => {
108
+ "type" => "number",
109
+ "minimum" => 0,
110
+ "maximum" => 100
111
+ }
112
+ }
113
+ }}
114
+
115
+ it_should_behave_like "valid schema generator"
116
+ end
117
+
118
+ describe "integer properties" do
119
+ subject { Class.new(JSONTestClass) {
120
+ schema "void", :root_element => false do
121
+ integer_property "cromulent", :minimum => 0, :maximum => 100
122
+ end
123
+ }}
124
+
125
+ its(:as_json) { should == {
126
+ "name" => "void",
127
+ "type" => "object",
128
+ "properties" => {
129
+ "cromulent" => {
130
+ "type" => "integer",
131
+ "minimum" => 0,
132
+ "maximum" => 100
133
+ }
134
+ }
135
+ }}
136
+
137
+ it_should_behave_like "valid schema generator"
138
+ end
139
+
140
+ describe "any properties" do
141
+ subject { Class.new(JSONTestClass) {
142
+ schema "void", :root_element => false do
143
+ any_property "enlightened"
144
+ end
145
+ }}
146
+
147
+ its(:as_json) { should == {
148
+ "name" => "void",
149
+ "type" => "object",
150
+ "properties" => {
151
+ "enlightened" => {
152
+ "type" => "any"
153
+ }
154
+ }
155
+ }}
156
+
157
+ it_should_behave_like "valid schema generator"
158
+ end
159
+
160
+ describe "boolean properties" do
161
+ subject { Class.new(JSONTestClass) {
162
+ schema "void", :root_element => false do
163
+ boolean_property "robot"
164
+ end
165
+ }}
166
+
167
+ its(:as_json) { should == {
168
+ "name" => "void",
169
+ "type" => "object",
170
+ "properties" => {
171
+ "robot" => {
172
+ "type" => "boolean"
173
+ }
174
+ }
175
+ }}
176
+
177
+ it_should_behave_like "valid schema generator"
178
+ end
179
+
180
+ describe "union properties" do
181
+ subject { Class.new(JSONTestClass) {
182
+ schema "void", :root_element => false do
183
+ union_property "teachers", [:string, :null]
184
+ end
185
+ }}
186
+
187
+ its(:as_json) { should == {
188
+ "name" => "void",
189
+ "type" => "object",
190
+ "properties" => {
191
+ "teachers" => {
192
+ "type" => ["string", "null"]
193
+ }
194
+ }
195
+ }}
196
+
197
+ it_should_behave_like "valid schema generator"
198
+ end
199
+
200
+ describe "array properties" do
201
+ subject { Class.new(JSONTestClass) {
202
+ schema "void", :root_element => false do
203
+ array_property "colors",
204
+ :enum => [['blue', true], ['red', false], ['green', true]],
205
+ :required => true do
206
+ string_property :enum => %w[blue red green]
207
+ boolean_property
208
+ end
209
+
210
+ array_property "suppliers" do
211
+ ref_property "http://example.com/supplier.json"
212
+ end
213
+
214
+ array_property "sizes" do
215
+ integer_property :enum => [1,2,3,4,5,6]
216
+ end
217
+ end
218
+ }}
219
+
220
+ its(:as_json) { should == {
221
+ "name" => "void",
222
+ "type" => "object",
223
+ "properties" => {
224
+ "colors" => {
225
+ "type" => "array",
226
+ "required" => true,
227
+ "enum" => [['blue', true], ['red', false], ['green', true]],
228
+ "items" => [
229
+ {
230
+ "type" => "string",
231
+ "enum" => %w[blue red green]
232
+ },
233
+ {
234
+ "type" => "boolean"
235
+ }
236
+ ]
237
+ },
238
+ "suppliers" => {
239
+ "type" => "array",
240
+ "items" => {
241
+ "$ref" => "http://example.com/supplier.json"
242
+ }
243
+ },
244
+ "sizes" => {
245
+ "type" => "array",
246
+ "items" => {
247
+ "type" => "integer",
248
+ "enum" => [1,2,3,4,5,6]
249
+ }
250
+ }
251
+ }
252
+ }}
253
+
254
+ it_should_behave_like "valid schema generator"
255
+ end
256
+
257
+ describe "object properties" do
258
+ subject { Class.new(JSONTestClass) {
259
+ schema "void", :root_element => false do
260
+ object_property "attributes", :required => true do
261
+ string_property "color", :enum => %w[red blue green]
262
+ end
263
+ end
264
+ }}
265
+
266
+ its(:as_json) { should == {
267
+ "name" => "void",
268
+ "type" => "object",
269
+ "properties" => {
270
+ "attributes" => {
271
+ "type" => "object",
272
+ "required" => true,
273
+ "properties" => {
274
+ "color" => {
275
+ "type" => "string",
276
+ "enum" => %w[red blue green]
277
+ }
278
+ }
279
+ }
280
+ }
281
+ }}
282
+
283
+ it_should_behave_like "valid schema generator"
284
+ end
285
+
286
+ describe "$ref properties" do
287
+ subject { Class.new(JSONTestClass) {
288
+ schema "void", :root_element => false do
289
+ ref_property "money", "http://example.com/money.json"
290
+ end
291
+ }}
292
+
293
+ its(:as_json) { should == {
294
+ "name" => "void",
295
+ "type" => "object",
296
+ "properties" => {
297
+ "money" => {
298
+ "$ref" => "http://example.com/money.json"
299
+ }
300
+ }
301
+ }}
302
+
303
+ it_should_behave_like "valid schema generator"
304
+ end
305
+
306
+ describe "overriding root element" do
307
+ subject { Class.new(JSONTestClass) {
308
+ schema "void", :root_element => "wat" do
309
+ end
310
+ }}
311
+
312
+ its(:as_json) { should == {
313
+ "name" => "void",
314
+ "type" => "object",
315
+ "properties" => {
316
+ "wat" => {
317
+ "type" => "object",
318
+ "properties" => {}
319
+ }
320
+ }
321
+ }}
322
+
323
+ it_should_behave_like "valid schema generator"
324
+ end
325
+ end
@@ -0,0 +1,22 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+
12
+ # Run specs in random order to surface order dependencies. If you find an
13
+ # order dependency and want to debug it, you can fix the order by providing
14
+ # the seed, which is printed after each run.
15
+ # --seed 1234
16
+ config.order = 'random'
17
+
18
+ require File.join(File.dirname(__FILE__), "json_validator_matchers")
19
+ config.include(JSONValidatorMatchers)
20
+ end
21
+
22
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'sexy_json_schemas')
metadata ADDED
@@ -0,0 +1,224 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sexy_json_schemas
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Donald Plummer
9
+ - Michael Xavier
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-09-27 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rake
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: 0.9.2
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ version: 0.9.2
31
+ - !ruby/object:Gem::Dependency
32
+ name: rspec
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ~>
37
+ - !ruby/object:Gem::Version
38
+ version: 2.11.0
39
+ type: :development
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: 2.11.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: guard
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.2.1
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ~>
61
+ - !ruby/object:Gem::Version
62
+ version: 1.2.1
63
+ - !ruby/object:Gem::Dependency
64
+ name: guard-rspec
65
+ requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ~>
69
+ - !ruby/object:Gem::Version
70
+ version: 1.1.0
71
+ type: :development
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ~>
77
+ - !ruby/object:Gem::Version
78
+ version: 1.1.0
79
+ - !ruby/object:Gem::Dependency
80
+ name: fivemat
81
+ requirement: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ~>
85
+ - !ruby/object:Gem::Version
86
+ version: 1.1.0
87
+ type: :development
88
+ prerelease: false
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ~>
93
+ - !ruby/object:Gem::Version
94
+ version: 1.1.0
95
+ - !ruby/object:Gem::Dependency
96
+ name: rb-inotify
97
+ requirement: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ~>
101
+ - !ruby/object:Gem::Version
102
+ version: 0.8.8
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: 0.8.8
111
+ - !ruby/object:Gem::Dependency
112
+ name: require_relative
113
+ requirement: !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ~>
117
+ - !ruby/object:Gem::Version
118
+ version: 1.0.3
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ~>
125
+ - !ruby/object:Gem::Version
126
+ version: 1.0.3
127
+ - !ruby/object:Gem::Dependency
128
+ name: json-schema
129
+ requirement: !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - ~>
133
+ - !ruby/object:Gem::Version
134
+ version: 1.0.9
135
+ type: :development
136
+ prerelease: false
137
+ version_requirements: !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ~>
141
+ - !ruby/object:Gem::Version
142
+ version: 1.0.9
143
+ - !ruby/object:Gem::Dependency
144
+ name: json
145
+ requirement: !ruby/object:Gem::Requirement
146
+ none: false
147
+ requirements:
148
+ - - ~>
149
+ - !ruby/object:Gem::Version
150
+ version: 1.7.5
151
+ type: :development
152
+ prerelease: false
153
+ version_requirements: !ruby/object:Gem::Requirement
154
+ none: false
155
+ requirements:
156
+ - - ~>
157
+ - !ruby/object:Gem::Version
158
+ version: 1.7.5
159
+ description: A DSL for generating JSON Schemas
160
+ email:
161
+ - donald@crystalcommerce.com
162
+ - xavier@crystalcommerce.com
163
+ executables: []
164
+ extensions: []
165
+ extra_rdoc_files: []
166
+ files:
167
+ - .gitignore
168
+ - .rspec
169
+ - .rvmrc
170
+ - Gemfile
171
+ - Guardfile
172
+ - LICENSE.txt
173
+ - README.md
174
+ - Rakefile
175
+ - lib/sexy_json_schemas.rb
176
+ - lib/sexy_json_schemas/dsl.rb
177
+ - lib/sexy_json_schemas/properties/anonymous_object.rb
178
+ - lib/sexy_json_schemas/properties/any.rb
179
+ - lib/sexy_json_schemas/properties/array.rb
180
+ - lib/sexy_json_schemas/properties/base.rb
181
+ - lib/sexy_json_schemas/properties/boolean.rb
182
+ - lib/sexy_json_schemas/properties/integer.rb
183
+ - lib/sexy_json_schemas/properties/null.rb
184
+ - lib/sexy_json_schemas/properties/number.rb
185
+ - lib/sexy_json_schemas/properties/object.rb
186
+ - lib/sexy_json_schemas/properties/ref.rb
187
+ - lib/sexy_json_schemas/properties/string.rb
188
+ - lib/sexy_json_schemas/properties/union.rb
189
+ - lib/sexy_json_schemas/schema_definition.rb
190
+ - sexy_json_schemas.gemspec
191
+ - spec/json_schema.schema
192
+ - spec/json_validator_matchers.rb
193
+ - spec/sexy_json_schemas_spec.rb
194
+ - spec/spec_helper.rb
195
+ homepage: http://github.com/crystalcommerce/sexy_json_schemas
196
+ licenses: []
197
+ post_install_message:
198
+ rdoc_options: []
199
+ require_paths:
200
+ - lib
201
+ required_ruby_version: !ruby/object:Gem::Requirement
202
+ none: false
203
+ requirements:
204
+ - - ! '>='
205
+ - !ruby/object:Gem::Version
206
+ version: '0'
207
+ required_rubygems_version: !ruby/object:Gem::Requirement
208
+ none: false
209
+ requirements:
210
+ - - ! '>='
211
+ - !ruby/object:Gem::Version
212
+ version: '0'
213
+ requirements: []
214
+ rubyforge_project:
215
+ rubygems_version: 1.8.24
216
+ signing_key:
217
+ specification_version: 3
218
+ summary: A DSL for generating JSON Schemas
219
+ test_files:
220
+ - spec/json_schema.schema
221
+ - spec/json_validator_matchers.rb
222
+ - spec/sexy_json_schemas_spec.rb
223
+ - spec/spec_helper.rb
224
+ has_rdoc: