json-schema_builder 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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