sexy_json_schemas 0.0.5

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.
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: