json-schema_builder 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0f90789d3f3f12de9b7b3ae15e7e33f6fb845f7c
4
- data.tar.gz: 38984c38614450bea747ee03441add545c4d5bc0
3
+ metadata.gz: 082f36b316c2da4de5d21d907ed6cbf6f6856054
4
+ data.tar.gz: 9210568145ac172ce05396f3bb529b88e9aa82a1
5
5
  SHA512:
6
- metadata.gz: 64e60e98e0c21a9dab31b5136e6712c9c2000c97d1f3545859228041b12b02c3d69e68c7a605dfa5c52a626450ef8e4f5acb028aa13ee097a691fad41c9cdba1
7
- data.tar.gz: 9046c88b826c5227990fb3456f5b529d9674b50b58c6545fdd2e0e4083caee6067b675da1d2e97083c4b5efb8e62d1ed102f1eb1597a8836c03224f2d75b246d
6
+ metadata.gz: 92ea3b1d9739cd6f7eff349d5f67a2706a9897925089bf3ed4efcb39dae9b1a83d8b8dfafe21cfb1921f886fcd0a6e24b83792c12b6b1b23fd549519d754eea7
7
+ data.tar.gz: 9cf96de81566436992fa384ca0cf3be326956581d36b0beb4bd006776b5846047881e61d2521b628750f3406c0e1fd5d12c51b0ce13c3b4b84ecc706b115a980
data/.gitignore CHANGED
@@ -1,2 +1,4 @@
1
1
  /.bundle/
2
+ /pkg
3
+ /coverage
2
4
  .DS_Store
data/.travis.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  language: ruby
2
- script: rspec
2
+ script: bundle exec rspec
3
3
  rvm:
4
4
  - 2.1.5
5
5
  addons:
data/Gemfile.lock CHANGED
@@ -1,8 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- json-schema_builder (0.0.1)
4
+ json-schema_builder (0.0.2)
5
5
  activesupport (~> 4.0, = 4.2.0.rc2)
6
+ json-schema (~> 2.5)
6
7
 
7
8
  GEM
8
9
  remote: https://rubygems.org/
@@ -13,6 +14,7 @@ GEM
13
14
  minitest (~> 5.1)
14
15
  thread_safe (~> 0.1)
15
16
  tzinfo (~> 1.1)
17
+ addressable (2.3.6)
16
18
  codeclimate-test-reporter (0.4.3)
17
19
  simplecov (>= 0.7.1, < 1.0.0)
18
20
  coderay (1.1.0)
@@ -20,8 +22,10 @@ GEM
20
22
  docile (1.1.5)
21
23
  i18n (0.7.0.beta1)
22
24
  json (1.8.1)
25
+ json-schema (2.5.0)
26
+ addressable (~> 2.3)
23
27
  method_source (0.8.2)
24
- minitest (5.4.3)
28
+ minitest (5.5.0)
25
29
  multi_json (1.10.1)
26
30
  pry (0.10.1)
27
31
  coderay (~> 1.1.0)
data/README.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # JSON::SchemaBuilder
2
2
 
3
- TODO: Write a gem description
3
+ [![Code Climate](https://codeclimate.com/github/parrish/json-schema_builder/badges/gpa.svg)](https://codeclimate.com/github/parrish/json-schema_builder)
4
+ [![Test Coverage](https://codeclimate.com/github/parrish/json-schema_builder/badges/coverage.svg)](https://codeclimate.com/github/parrish/json-schema_builder)
5
+ [![Gem Version](https://badge.fury.io/rb/json-schema_builder.svg)](http://badge.fury.io/rb/json-schema_builder)
6
+
7
+ Build JSON schemas with Ruby
4
8
 
5
9
  ## Installation
6
10
 
@@ -25,4 +25,5 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency 'codeclimate-test-reporter'
26
26
  spec.add_development_dependency 'pry'
27
27
  spec.add_dependency 'activesupport', '~> 4.0', '4.2.0.rc2'
28
+ spec.add_dependency 'json-schema', '~> 2.5'
28
29
  end
@@ -0,0 +1,45 @@
1
+ module JSON
2
+ module SchemaBuilder
3
+ module Attribute
4
+ extend ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+ def attribute(name, as: nil, array: false)
8
+ attr = as || snakeize(name)
9
+ define_method name do |*values|
10
+ if array
11
+ _array_attr attr, values.flatten
12
+ else
13
+ _attr attr, values.first
14
+ end
15
+ end
16
+ alias_method "#{ name }=", name
17
+ end
18
+
19
+ protected
20
+
21
+ def snakeize(str)
22
+ str.to_s.underscore.gsub(/_(\w)/){ $1.upcase }
23
+ end
24
+ end
25
+
26
+ protected
27
+
28
+ def _array_attr(attr, values)
29
+ if values.empty?
30
+ self.schema[attr]
31
+ else
32
+ self.schema[attr] = values
33
+ end
34
+ end
35
+
36
+ def _attr(attr, value)
37
+ if value.nil?
38
+ self.schema[attr]
39
+ else
40
+ self.schema[attr] = value
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,22 @@
1
+ require 'ostruct'
2
+
3
+ module JSON
4
+ module SchemaBuilder
5
+ module Configuration
6
+ def options
7
+ return @options if @options
8
+ defaults = JSON::SchemaBuilder.default_options
9
+ @options = OpenStruct.new defaults.to_h
10
+ end
11
+
12
+ def options=(config)
13
+ @options = OpenStruct.new config.to_h
14
+ end
15
+
16
+ def configure
17
+ @options = nil
18
+ yield(options) if block_given?
19
+ end
20
+ end
21
+ end
22
+ end
@@ -7,12 +7,20 @@ module JSON
7
7
  def entity(*args, &block)
8
8
  opts = args.extract_options!
9
9
  klass, name = klass_and_name_from args
10
- opts[:parent] ||= self if is_a?(Entity)
10
+ set_context_for opts
11
11
  klass.new name, opts, &block
12
12
  end
13
13
 
14
14
  protected
15
15
 
16
+ def set_context_for(opts)
17
+ if is_a?(Entity)
18
+ opts[:parent] ||= self
19
+ else
20
+ opts[:root] = self
21
+ end
22
+ end
23
+
16
24
  def klass_and_name_from(args)
17
25
  type, name = args
18
26
  if DSL.types[type]
@@ -1,35 +1,28 @@
1
1
  require_relative 'dsl'
2
2
  require_relative 'schema'
3
+ require_relative 'attribute'
4
+ require_relative 'validation'
3
5
 
4
6
  module JSON
5
7
  module SchemaBuilder
6
8
  class Entity
7
9
  include DSL
10
+ include Attribute
11
+ include Validation
8
12
  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
13
+ attr_accessor :name, :parent, :children, :options
23
14
 
24
15
  attribute :title
25
16
  attribute :description
26
17
 
27
18
  attribute :type
19
+ attribute :default
28
20
  attribute :enum, array: true
29
21
  attribute :all_of, array: true
30
22
  attribute :any_of, array: true
31
23
  attribute :one_of, array: true
32
24
  attribute :not_a, as: :not
25
+ attribute :ref, as: :$ref
33
26
  attribute :definitions
34
27
 
35
28
  def initialize(name, opts = { }, &block)
@@ -84,6 +77,7 @@ module JSON
84
77
  end
85
78
 
86
79
  def initialize_with(opts)
80
+ @options = opts.delete(:root).class.options.to_h if opts[:root]
87
81
  opts.each_pair do |key, value|
88
82
  next if value.nil?
89
83
  send :"#{ key }=", value
@@ -0,0 +1,26 @@
1
+ require 'json-schema'
2
+
3
+ module JSON
4
+ module SchemaBuilder
5
+ module Validation
6
+ def validate(data, opts = { })
7
+ _validate :validate, data, opts
8
+ end
9
+
10
+ def validate!(data, opts = { })
11
+ _validate :validate!, data, opts
12
+ end
13
+
14
+ def fully_validate(data, opts = { })
15
+ _validate :fully_validate, data, opts
16
+ end
17
+
18
+ protected
19
+
20
+ def _validate(validator, data, opts)
21
+ opts.reverse_merge! options if options
22
+ JSON::Validator.send validator, as_json, data, opts
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,5 +1,5 @@
1
1
  module JSON
2
2
  module SchemaBuilder
3
- VERSION = '0.0.1'
3
+ VERSION = '0.0.2'
4
4
  end
5
5
  end
@@ -2,6 +2,7 @@ require 'active_support'
2
2
  require 'active_support/core_ext'
3
3
  require 'json/schema_builder/dsl'
4
4
  require 'json/schema_builder/version'
5
+ require 'json/schema_builder/configuration'
5
6
 
6
7
  %w(array boolean integer null number object string).each do |type|
7
8
  require "json/schema_builder/#{ type }"
@@ -9,6 +10,16 @@ end
9
10
 
10
11
  module JSON
11
12
  module SchemaBuilder
13
+ extend ActiveSupport::Concern
12
14
  include DSL
15
+ extend JSON::SchemaBuilder::Configuration
16
+
17
+ included do |klass|
18
+ extend JSON::SchemaBuilder::Configuration
19
+ end
20
+
21
+ def self.default_options
22
+ @options || { }
23
+ end
13
24
  end
14
25
  end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Examples::ArrayDefinitions, type: :integration do
4
+ it_behaves_like 'a builder' do
5
+ let(:expected_json) do
6
+ {
7
+ type: :array,
8
+ definitions: {
9
+ positiveInt: {
10
+ type: :integer,
11
+ minimum: 0,
12
+ exclusiveMinimum: true
13
+ }
14
+ },
15
+ items: {
16
+ :$ref => '#/definitions/positiveInt'
17
+ }
18
+ }
19
+ end
20
+ end
21
+ end
@@ -37,4 +37,10 @@ RSpec.describe Examples::EntityLiterals, type: :integration do
37
37
  }
38
38
  end
39
39
  end
40
+
41
+ it 'should raise through missing methods' do
42
+ expect {
43
+ described_class.new.bad_example
44
+ }.to raise_error NameError
45
+ end
40
46
  end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Examples::MixedObjects, type: :integration do
4
+ it_behaves_like 'a builder' do
5
+ let(:expected_json) do
6
+ {
7
+ type: :object,
8
+ required: [:one],
9
+ properties: {
10
+ one: {
11
+ type: :object,
12
+ properties: { }
13
+ }
14
+ }
15
+ }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Examples::ObjectDefinitions, type: :integration do
4
+ it_behaves_like 'a builder' do
5
+ let(:expected_json) do
6
+ {
7
+ type: :object,
8
+ definitions: {
9
+ positiveInt: {
10
+ type: :integer,
11
+ minimum: 0,
12
+ exclusiveMinimum: true
13
+ }
14
+ },
15
+ properties: {
16
+ one: {
17
+ :$ref => '#/definitions/positiveInt'
18
+ }
19
+ }
20
+ }
21
+ end
22
+ end
23
+ end
@@ -16,4 +16,60 @@ RSpec.describe Examples::SchemaBuilder, type: :integration do
16
16
  end
17
17
  end
18
18
  end
19
+
20
+ describe 'Configuration' do
21
+ subject{ Examples::SchemaBuilder }
22
+ after(:all) do
23
+ JSON::SchemaBuilder.configure
24
+ Examples::SchemaBuilder.configure
25
+ end
26
+
27
+ describe '.options=' do
28
+ before(:each){ subject.options = { a: 1 } }
29
+
30
+ its(:options){ is_expected.to be_a OpenStruct }
31
+ its('options.to_h'){ is_expected.to eql a: 1 }
32
+ end
33
+
34
+ describe '.configure' do
35
+ before(:each) do
36
+ subject.configure{ |opts| opts.validate_schema = true }
37
+ end
38
+
39
+ its(:options){ is_expected.to be_a OpenStruct }
40
+ its('options.to_h'){ is_expected.to eql validate_schema: true }
41
+
42
+ context 'with default options' do
43
+ after(:each){ subject.configure }
44
+ before(:each) do
45
+ JSON::SchemaBuilder.configure do |opts|
46
+ opts.insert_defaults = true
47
+ opts.validate_schema = false
48
+ end
49
+
50
+ subject.configure do |opts|
51
+ opts.validate_schema = true
52
+ end
53
+ end
54
+
55
+ its('options.insert_defaults'){ is_expected.to be true }
56
+ its('options.validate_schema'){ is_expected.to be true }
57
+ end
58
+
59
+ it 'should reset configuration first' do
60
+ subject.configure
61
+ expect(subject.options.validate_schema).to be nil
62
+ end
63
+
64
+ it 'should pass options to root entities' do
65
+ entity = subject.new.example
66
+ expect(entity.options).to eql validate_schema: true
67
+ end
68
+
69
+ it 'should not pass options to child entities' do
70
+ entity = subject.new.example.children.first
71
+ expect(entity.options).to be nil
72
+ end
73
+ end
74
+ end
19
75
  end
data/spec/spec_helper.rb CHANGED
@@ -1,11 +1,15 @@
1
1
  require 'pry'
2
+ require 'simplecov'
3
+ SimpleCov.configure do
4
+ add_filter '/spec'
5
+ end
6
+
7
+ SimpleCov.start
8
+
2
9
  %w(lib spec/support).each do |path|
3
10
  Dir["./#{ path }/**/*.rb"].sort.each{ |file| require file }
4
11
  end
5
12
 
6
- require 'codeclimate-test-reporter'
7
- CodeClimate::TestReporter.start
8
-
9
13
  require 'rspec/its'
10
14
  RSpec.configure do |config|
11
15
  config.disable_monkey_patching!
@@ -0,0 +1,19 @@
1
+ module Examples
2
+ class ArrayDefinitions
3
+ include JSON::SchemaBuilder
4
+
5
+ def example
6
+ array do
7
+ definitions positiveInt: positive_int
8
+ items ref: '#/definitions/positiveInt'
9
+ end
10
+ end
11
+
12
+ def positive_int
13
+ integer do
14
+ minimum 0
15
+ exclusive_minimum true
16
+ end
17
+ end
18
+ end
19
+ end
@@ -26,6 +26,14 @@ module Examples
26
26
  end
27
27
  end
28
28
 
29
+ def bad_example
30
+ object do
31
+ entity 'bad' do
32
+ not_a undefined_method
33
+ end
34
+ end
35
+ end
36
+
29
37
  def positive_int
30
38
  integer minimum: 1
31
39
  end
@@ -0,0 +1,11 @@
1
+ module Examples
2
+ class MixedObjects
3
+ include JSON::SchemaBuilder
4
+
5
+ def example
6
+ object do
7
+ object :one, required: true
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ module Examples
2
+ class ObjectDefinitions
3
+ include JSON::SchemaBuilder
4
+
5
+ def example
6
+ object do
7
+ definitions positiveInt: positive_int
8
+ entity :one, ref: '#/definitions/positiveInt'
9
+ end
10
+ end
11
+
12
+ def positive_int
13
+ integer do
14
+ minimum 0
15
+ exclusive_minimum true
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,5 +1,11 @@
1
1
  module Examples
2
2
  class SchemaBuilder
3
3
  include JSON::SchemaBuilder
4
+
5
+ def example
6
+ object do
7
+ string :name, required: true
8
+ end
9
+ end
4
10
  end
5
11
  end
@@ -42,7 +42,7 @@ RSpec.describe JSON::SchemaBuilder::DSL, type: :unit do
42
42
  context 'without an entity' do
43
43
  it 'should create the type' do
44
44
  expect(instance.class).to receive(:new)
45
- .with('name', { }).and_call_original
45
+ .with('name', { root: instance.class }).and_call_original
46
46
 
47
47
  entity = instance.entity :something, 'name'
48
48
  expect(entity).to be_a klass
@@ -6,11 +6,13 @@ RSpec.describe JSON::SchemaBuilder::Entity, type: :unit do
6
6
  it{ is_expected.to define_attribute :title }
7
7
  it{ is_expected.to define_attribute :description }
8
8
  it{ is_expected.to define_attribute :type }
9
+ it{ is_expected.to define_attribute :default }
9
10
  it{ is_expected.to define_attribute :enum }
10
11
  it{ is_expected.to define_attribute :all_of }
11
12
  it{ is_expected.to define_attribute :any_of }
12
13
  it{ is_expected.to define_attribute :one_of }
13
14
  it{ is_expected.to define_attribute :not_a }
15
+ it{ is_expected.to define_attribute :ref }
14
16
  it{ is_expected.to define_attribute :definitions }
15
17
 
16
18
  describe '.attribute' do
@@ -45,7 +47,12 @@ RSpec.describe JSON::SchemaBuilder::Entity, type: :unit do
45
47
  expect(subject.schema.testName).to eql 1
46
48
  end
47
49
 
48
- it 'should handle array arguments' do
50
+ it 'should handle array argument reads' do
51
+ subject.schema.testList = [1, 2, 3]
52
+ expect(subject.test_list).to eql [1, 2, 3]
53
+ end
54
+
55
+ it 'should handle array argument writes' do
49
56
  subject.test_list = [1, 2, 3]
50
57
  expect(subject.schema.testList).to eql [1, 2, 3]
51
58
  end
@@ -89,6 +96,28 @@ RSpec.describe JSON::SchemaBuilder::Entity, type: :unit do
89
96
  end
90
97
  end
91
98
 
99
+ %w(validate validate! fully_validate).each do |validator|
100
+ describe "##{ validator }" do
101
+ let(:klass) do
102
+ Class.new do
103
+ include JSON::SchemaBuilder
104
+ configure{ |opts| opts.working = true }
105
+
106
+ def example
107
+ object{ string :name }
108
+ end
109
+ end
110
+ end
111
+ subject{ klass.new.example }
112
+
113
+ it "should #{ validator }" do
114
+ expect(JSON::Validator).to receive(validator)
115
+ .with subject.as_json, { }, working: true, opts: true
116
+ subject.send validator, { }, opts: true
117
+ end
118
+ end
119
+ end
120
+
92
121
  describe '#merge_children!' do
93
122
  include_context 'an entity with a parent'
94
123
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json-schema_builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Parrish
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-15 00:00:00.000000000 Z
11
+ date: 2014-12-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -114,6 +114,20 @@ dependencies:
114
114
  - - '='
115
115
  - !ruby/object:Gem::Version
116
116
  version: 4.2.0.rc2
117
+ - !ruby/object:Gem::Dependency
118
+ name: json-schema
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '2.5'
124
+ type: :runtime
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '2.5'
117
131
  description: Build JSON schemas with Ruby
118
132
  email:
119
133
  - michael@zooniverse.org
@@ -132,7 +146,9 @@ files:
132
146
  - json-schema_builder.gemspec
133
147
  - lib/json/schema_builder.rb
134
148
  - lib/json/schema_builder/array.rb
149
+ - lib/json/schema_builder/attribute.rb
135
150
  - lib/json/schema_builder/boolean.rb
151
+ - lib/json/schema_builder/configuration.rb
136
152
  - lib/json/schema_builder/dsl.rb
137
153
  - lib/json/schema_builder/entity.rb
138
154
  - lib/json/schema_builder/integer.rb
@@ -142,9 +158,13 @@ files:
142
158
  - lib/json/schema_builder/object.rb
143
159
  - lib/json/schema_builder/schema.rb
144
160
  - lib/json/schema_builder/string.rb
161
+ - lib/json/schema_builder/validation.rb
145
162
  - lib/json/schema_builder/version.rb
163
+ - spec/integration/array_definitions_spec.rb
146
164
  - spec/integration/entity_literals_spec.rb
147
165
  - spec/integration/mixed_arrays_spec.rb
166
+ - spec/integration/mixed_objects_spec.rb
167
+ - spec/integration/object_definitions_spec.rb
148
168
  - spec/integration/schema_builder_spec.rb
149
169
  - spec/integration/terse_arrays_spec.rb
150
170
  - spec/integration/terse_objects_spec.rb
@@ -153,8 +173,11 @@ files:
153
173
  - spec/spec_helper.rb
154
174
  - spec/support/.keep
155
175
  - spec/support/attribute_matcher.rb
176
+ - spec/support/examples/array_definitions.rb
156
177
  - spec/support/examples/entity_literals.rb
157
178
  - spec/support/examples/mixed_arrays.rb
179
+ - spec/support/examples/mixed_objects.rb
180
+ - spec/support/examples/object_definitions.rb
158
181
  - spec/support/examples/schema_builder.rb
159
182
  - spec/support/examples/terse_arrays.rb
160
183
  - spec/support/examples/terse_objects.rb
@@ -198,8 +221,11 @@ signing_key:
198
221
  specification_version: 4
199
222
  summary: Build JSON schemas with Ruby
200
223
  test_files:
224
+ - spec/integration/array_definitions_spec.rb
201
225
  - spec/integration/entity_literals_spec.rb
202
226
  - spec/integration/mixed_arrays_spec.rb
227
+ - spec/integration/mixed_objects_spec.rb
228
+ - spec/integration/object_definitions_spec.rb
203
229
  - spec/integration/schema_builder_spec.rb
204
230
  - spec/integration/terse_arrays_spec.rb
205
231
  - spec/integration/terse_objects_spec.rb
@@ -208,8 +234,11 @@ test_files:
208
234
  - spec/spec_helper.rb
209
235
  - spec/support/.keep
210
236
  - spec/support/attribute_matcher.rb
237
+ - spec/support/examples/array_definitions.rb
211
238
  - spec/support/examples/entity_literals.rb
212
239
  - spec/support/examples/mixed_arrays.rb
240
+ - spec/support/examples/mixed_objects.rb
241
+ - spec/support/examples/object_definitions.rb
213
242
  - spec/support/examples/schema_builder.rb
214
243
  - spec/support/examples/terse_arrays.rb
215
244
  - spec/support/examples/terse_objects.rb