json-schema_builder 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +8 -0
  5. data/Gemfile +2 -0
  6. data/Gemfile.lock +66 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +31 -0
  9. data/Rakefile +1 -0
  10. data/json-schema_builder.gemspec +28 -0
  11. data/lib/json/schema_builder.rb +14 -0
  12. data/lib/json/schema_builder/array.rb +29 -0
  13. data/lib/json/schema_builder/boolean.rb +9 -0
  14. data/lib/json/schema_builder/dsl.rb +42 -0
  15. data/lib/json/schema_builder/entity.rb +101 -0
  16. data/lib/json/schema_builder/integer.rb +9 -0
  17. data/lib/json/schema_builder/null.rb +9 -0
  18. data/lib/json/schema_builder/number.rb +9 -0
  19. data/lib/json/schema_builder/numeric.rb +13 -0
  20. data/lib/json/schema_builder/object.rb +36 -0
  21. data/lib/json/schema_builder/schema.rb +16 -0
  22. data/lib/json/schema_builder/string.rb +12 -0
  23. data/lib/json/schema_builder/version.rb +5 -0
  24. data/spec/integration/entity_literals_spec.rb +40 -0
  25. data/spec/integration/mixed_arrays_spec.rb +16 -0
  26. data/spec/integration/schema_builder_spec.rb +19 -0
  27. data/spec/integration/terse_arrays_spec.rb +18 -0
  28. data/spec/integration/terse_objects_spec.rb +30 -0
  29. data/spec/integration/verbose_arrays_spec.rb +18 -0
  30. data/spec/integration/verbose_objects_spec.rb +30 -0
  31. data/spec/spec_helper.rb +13 -0
  32. data/spec/support/.keep +0 -0
  33. data/spec/support/attribute_matcher.rb +17 -0
  34. data/spec/support/examples/entity_literals.rb +33 -0
  35. data/spec/support/examples/mixed_arrays.rb +14 -0
  36. data/spec/support/examples/schema_builder.rb +5 -0
  37. data/spec/support/examples/terse_arrays.rb +11 -0
  38. data/spec/support/examples/terse_objects.rb +16 -0
  39. data/spec/support/examples/verbose_arrays.rb +19 -0
  40. data/spec/support/examples/verbose_objects.rb +24 -0
  41. data/spec/support/integration_helper.rb +12 -0
  42. data/spec/support/shared_contexts_for_entity.rb +24 -0
  43. data/spec/support/shared_examples_for_numeric.rb +10 -0
  44. data/spec/unit/array_spec.rb +55 -0
  45. data/spec/unit/boolean_spec.rb +6 -0
  46. data/spec/unit/dsl_spec.rb +70 -0
  47. data/spec/unit/entity_spec.rb +114 -0
  48. data/spec/unit/integer_spec.rb +7 -0
  49. data/spec/unit/null_spec.rb +6 -0
  50. data/spec/unit/number_spec.rb +7 -0
  51. data/spec/unit/object_spec.rb +28 -0
  52. data/spec/unit/schema_spec.rb +35 -0
  53. data/spec/unit/string_spec.rb +10 -0
  54. metadata +230 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0f90789d3f3f12de9b7b3ae15e7e33f6fb845f7c
4
+ data.tar.gz: 38984c38614450bea747ee03441add545c4d5bc0
5
+ SHA512:
6
+ metadata.gz: 64e60e98e0c21a9dab31b5136e6712c9c2000c97d1f3545859228041b12b02c3d69e68c7a605dfa5c52a626450ef8e4f5acb028aa13ee097a691fad41c9cdba1
7
+ data.tar.gz: 9046c88b826c5227990fb3456f5b529d9674b50b58c6545fdd2e0e4083caee6067b675da1d2e97083c4b5efb8e62d1ed102f1eb1597a8836c03224f2d75b246d
@@ -0,0 +1,2 @@
1
+ /.bundle/
2
+ .DS_Store
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ script: rspec
3
+ rvm:
4
+ - 2.1.5
5
+ addons:
6
+ code_climate:
7
+ repo_token:
8
+ secure: X3mDel/6C4d8uSeaKgxA2YP4Oen5N2iklmi2mH1XzK3UihzlNKcQLxYC6IMTTfYiPlLu1BTO1KTElUqWIigpHxAAJj/Lb48S8mvKFAsmv48tOP5LaTeFNdnJA49k0hCXQbItlyVBmUhEtkdyelLciP3ygcKgEcR/jZGcJM/aZBY=
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
@@ -0,0 +1,66 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ json-schema_builder (0.0.1)
5
+ activesupport (~> 4.0, = 4.2.0.rc2)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activesupport (4.2.0.rc2)
11
+ i18n (>= 0.7.0.beta1, < 0.8)
12
+ json (~> 1.7, >= 1.7.7)
13
+ minitest (~> 5.1)
14
+ thread_safe (~> 0.1)
15
+ tzinfo (~> 1.1)
16
+ codeclimate-test-reporter (0.4.3)
17
+ simplecov (>= 0.7.1, < 1.0.0)
18
+ coderay (1.1.0)
19
+ diff-lcs (1.2.5)
20
+ docile (1.1.5)
21
+ i18n (0.7.0.beta1)
22
+ json (1.8.1)
23
+ method_source (0.8.2)
24
+ minitest (5.4.3)
25
+ multi_json (1.10.1)
26
+ pry (0.10.1)
27
+ coderay (~> 1.1.0)
28
+ method_source (~> 0.8.1)
29
+ slop (~> 3.4)
30
+ rake (10.4.2)
31
+ rspec (3.1.0)
32
+ rspec-core (~> 3.1.0)
33
+ rspec-expectations (~> 3.1.0)
34
+ rspec-mocks (~> 3.1.0)
35
+ rspec-core (3.1.7)
36
+ rspec-support (~> 3.1.0)
37
+ rspec-expectations (3.1.2)
38
+ diff-lcs (>= 1.2.0, < 2.0)
39
+ rspec-support (~> 3.1.0)
40
+ rspec-its (1.1.0)
41
+ rspec-core (>= 3.0.0)
42
+ rspec-expectations (>= 3.0.0)
43
+ rspec-mocks (3.1.3)
44
+ rspec-support (~> 3.1.0)
45
+ rspec-support (3.1.2)
46
+ simplecov (0.9.1)
47
+ docile (~> 1.1.0)
48
+ multi_json (~> 1.0)
49
+ simplecov-html (~> 0.8.0)
50
+ simplecov-html (0.8.0)
51
+ slop (3.6.0)
52
+ thread_safe (0.3.4)
53
+ tzinfo (1.2.2)
54
+ thread_safe (~> 0.1)
55
+
56
+ PLATFORMS
57
+ ruby
58
+
59
+ DEPENDENCIES
60
+ bundler (~> 1.7)
61
+ codeclimate-test-reporter
62
+ json-schema_builder!
63
+ pry
64
+ rake (~> 10.0)
65
+ rspec (~> 3.1)
66
+ rspec-its
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Michael Parrish
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.
@@ -0,0 +1,31 @@
1
+ # JSON::SchemaBuilder
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'json-schema_builder'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install json-schema_builder
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it ( https://github.com/[my-github-username]/json-schema_builder/fork )
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 a new Pull Request
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path '../lib', __FILE__
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'json/schema_builder/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'json-schema_builder'
8
+ spec.version = JSON::SchemaBuilder::VERSION
9
+ spec.authors = ['Michael Parrish']
10
+ spec.email = ['michael@zooniverse.org']
11
+ spec.summary = 'Build JSON schemas with Ruby'
12
+ spec.description = 'Build JSON schemas with Ruby'
13
+ spec.homepage = 'https://github.com/parrish/json-schema_builder'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split "\x0"
17
+ spec.executables = []
18
+ spec.test_files = spec.files.grep(%r{^spec/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.7'
22
+ spec.add_development_dependency 'rake', '~> 10.0'
23
+ spec.add_development_dependency 'rspec', '~> 3.1'
24
+ spec.add_development_dependency 'rspec-its'
25
+ spec.add_development_dependency 'codeclimate-test-reporter'
26
+ spec.add_development_dependency 'pry'
27
+ spec.add_dependency 'activesupport', '~> 4.0', '4.2.0.rc2'
28
+ end
@@ -0,0 +1,14 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext'
3
+ require 'json/schema_builder/dsl'
4
+ require 'json/schema_builder/version'
5
+
6
+ %w(array boolean integer null number object string).each do |type|
7
+ require "json/schema_builder/#{ type }"
8
+ end
9
+
10
+ module JSON
11
+ module SchemaBuilder
12
+ include DSL
13
+ end
14
+ end
@@ -0,0 +1,29 @@
1
+ require_relative 'entity'
2
+
3
+ module JSON
4
+ module SchemaBuilder
5
+ class Array < Entity
6
+ register :array
7
+ attribute :additional_items
8
+ attribute :min_items
9
+ attribute :max_items
10
+ attribute :unique_items
11
+
12
+ def items(*args, &block)
13
+ opts = args.extract_options!
14
+ schema.items = args.first
15
+ schema.items ||= items_entity(opts, &block).as_json
16
+ end
17
+
18
+ protected
19
+
20
+ def items_entity(opts, &block)
21
+ if opts[:type]
22
+ send opts.delete(:type), opts, &block
23
+ else
24
+ Entity.new(nil, opts, &block).tap &:merge_children!
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,9 @@
1
+ require_relative 'entity'
2
+
3
+ module JSON
4
+ module SchemaBuilder
5
+ class Boolean < Entity
6
+ register :boolean
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,42 @@
1
+ module JSON
2
+ module SchemaBuilder
3
+ module DSL
4
+ extend ActiveSupport::Concern
5
+ mattr_accessor :types
6
+
7
+ def entity(*args, &block)
8
+ opts = args.extract_options!
9
+ klass, name = klass_and_name_from args
10
+ opts[:parent] ||= self if is_a?(Entity)
11
+ klass.new name, opts, &block
12
+ end
13
+
14
+ protected
15
+
16
+ def klass_and_name_from(args)
17
+ type, name = args
18
+ if DSL.types[type]
19
+ [DSL.types[type], name]
20
+ else
21
+ [Entity, type]
22
+ end
23
+ end
24
+
25
+ module ClassMethods
26
+ def register(type)
27
+ self.registered_type = type
28
+ DSL.types ||= { }
29
+ DSL.types[type] = self
30
+
31
+ DSL.module_eval do
32
+ define_method type do |*args, &block|
33
+ opts = args.extract_options!
34
+ name = args.first
35
+ entity type, name, opts, &block
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,101 @@
1
+ require_relative 'dsl'
2
+ require_relative 'schema'
3
+
4
+ module JSON
5
+ module SchemaBuilder
6
+ class Entity
7
+ include DSL
8
+ class_attribute :registered_type
9
+ attr_accessor :name, :parent, :children
10
+
11
+ def self.attribute(name, as: nil, array: false)
12
+ as_name = as || name.to_s.underscore.gsub(/_(\w)/){ $1.upcase }
13
+ define_method name do |*values|
14
+ value = array ? values.flatten : values.first
15
+ if (array && value.empty?) || value.nil?
16
+ self.schema[as_name]
17
+ else
18
+ self.schema[as_name] = value
19
+ end
20
+ end
21
+ alias_method "#{ name }=", name
22
+ end
23
+
24
+ attribute :title
25
+ attribute :description
26
+
27
+ attribute :type
28
+ attribute :enum, array: true
29
+ attribute :all_of, array: true
30
+ attribute :any_of, array: true
31
+ attribute :one_of, array: true
32
+ attribute :not_a, as: :not
33
+ attribute :definitions
34
+
35
+ def initialize(name, opts = { }, &block)
36
+ @name = name
37
+ @children = []
38
+ self.type = self.class.registered_type
39
+ initialize_parent_with opts
40
+ initialize_with opts
41
+ eval_block &block
42
+ end
43
+
44
+ def schema
45
+ @schema ||= Schema.new
46
+ end
47
+
48
+ def required=(*values)
49
+ @parent.required ||= []
50
+ @parent.required << @name
51
+ end
52
+
53
+ def merge_children!
54
+ children.each do |child|
55
+ schema.merge! child.schema
56
+ end
57
+ end
58
+
59
+ def as_json
60
+ schema.to_h.as_json
61
+ end
62
+
63
+ def respond_to?(method_name, include_all = false)
64
+ if @parent_context
65
+ @parent_context.respond_to? method_name, include_all
66
+ else
67
+ super
68
+ end
69
+ end
70
+
71
+ def method_missing(method_name, *args, &block)
72
+ if @parent_context && respond_to?(method_name, true)
73
+ @parent_context.send method_name, *args, &block
74
+ else
75
+ super
76
+ end
77
+ end
78
+
79
+ protected
80
+
81
+ def initialize_parent_with(opts)
82
+ @parent = opts.delete :parent
83
+ @parent.children << self if @parent
84
+ end
85
+
86
+ def initialize_with(opts)
87
+ opts.each_pair do |key, value|
88
+ next if value.nil?
89
+ send :"#{ key }=", value
90
+ end
91
+ end
92
+
93
+ def eval_block(&block)
94
+ if block_given?
95
+ @parent_context = block.binding.eval 'self'
96
+ instance_exec self, &block
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,9 @@
1
+ require_relative 'numeric'
2
+
3
+ module JSON
4
+ module SchemaBuilder
5
+ class Integer < Numeric
6
+ register :integer
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require_relative 'entity'
2
+
3
+ module JSON
4
+ module SchemaBuilder
5
+ class Null < Entity
6
+ register :null
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require_relative 'numeric'
2
+
3
+ module JSON
4
+ module SchemaBuilder
5
+ class Number < Numeric
6
+ register :number
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ require_relative 'entity'
2
+
3
+ module JSON
4
+ module SchemaBuilder
5
+ class Numeric < Entity
6
+ attribute :multiple_of
7
+ attribute :minimum
8
+ attribute :maximum
9
+ attribute :exclusive_minimum
10
+ attribute :exclusive_maximum
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,36 @@
1
+ require_relative 'entity'
2
+
3
+ module JSON
4
+ module SchemaBuilder
5
+ class Object < Entity
6
+ register :object
7
+ attribute :required
8
+ attribute :min_properties
9
+ attribute :max_properties
10
+ attribute :properties
11
+ attribute :additional_properties
12
+ attribute :pattern_properties
13
+
14
+ def initialize(name, opts = { }, &block)
15
+ self.properties = { }
16
+ super
17
+ children.each do |child|
18
+ self.properties[child.name] = child.as_json
19
+ end
20
+ end
21
+
22
+ def required(*values)
23
+ case values
24
+ when []
25
+ @schema.required
26
+ when [true]
27
+ @parent.required ||= []
28
+ @parent.required << @name
29
+ else
30
+ @schema.required = values.flatten
31
+ end
32
+ end
33
+ alias_method :required=, :required
34
+ end
35
+ end
36
+ end