json-schema_builder 0.4.0 → 0.5.0
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 +4 -4
- data/.travis.yml +40 -5
- data/Appraisals +6 -3
- data/gemfiles/{activesupport_4.0.gemfile → version_2.1.0_4.0.gemfile} +1 -0
- data/gemfiles/{activesupport_4.1.gemfile → version_2.1.0_4.1.gemfile} +1 -0
- data/gemfiles/{activesupport_4.2.gemfile → version_2.1.0_4.2.gemfile} +1 -0
- data/gemfiles/{activesupport_5.0.gemfile → version_2.1.0_5.0.gemfile} +1 -0
- data/gemfiles/{activesupport_5.1.gemfile → version_2.1.0_5.1.gemfile} +1 -0
- data/gemfiles/version_2.2.0_4.0.gemfile +8 -0
- data/gemfiles/version_2.2.0_4.1.gemfile +8 -0
- data/gemfiles/version_2.2.0_4.2.gemfile +8 -0
- data/gemfiles/version_2.2.0_5.0.gemfile +8 -0
- data/gemfiles/version_2.2.0_5.1.gemfile +8 -0
- data/gemfiles/version_2.3.0_4.0.gemfile +8 -0
- data/gemfiles/version_2.3.0_4.1.gemfile +8 -0
- data/gemfiles/version_2.3.0_4.2.gemfile +8 -0
- data/gemfiles/version_2.3.0_5.0.gemfile +8 -0
- data/gemfiles/version_2.3.0_5.1.gemfile +8 -0
- data/gemfiles/version_2.4.0_4.0.gemfile +8 -0
- data/gemfiles/version_2.4.0_4.1.gemfile +8 -0
- data/gemfiles/version_2.4.0_4.2.gemfile +8 -0
- data/gemfiles/version_2.4.0_5.0.gemfile +8 -0
- data/gemfiles/version_2.4.0_5.1.gemfile +8 -0
- data/gemfiles/version_2.5.0_4.0.gemfile +8 -0
- data/gemfiles/version_2.5.0_4.1.gemfile +8 -0
- data/gemfiles/version_2.5.0_4.2.gemfile +8 -0
- data/gemfiles/version_2.5.0_5.0.gemfile +8 -0
- data/gemfiles/version_2.5.0_5.1.gemfile +8 -0
- data/gemfiles/version_2.6.0_4.0.gemfile +8 -0
- data/gemfiles/version_2.6.0_4.1.gemfile +8 -0
- data/gemfiles/version_2.6.0_4.2.gemfile +8 -0
- data/gemfiles/version_2.6.0_5.0.gemfile +8 -0
- data/gemfiles/version_2.6.0_5.1.gemfile +8 -0
- data/gemfiles/version_2.7.0_4.0.gemfile +8 -0
- data/gemfiles/version_2.7.0_4.1.gemfile +8 -0
- data/gemfiles/version_2.7.0_4.2.gemfile +8 -0
- data/gemfiles/version_2.7.0_5.0.gemfile +8 -0
- data/gemfiles/version_2.7.0_5.1.gemfile +8 -0
- data/gemfiles/version_2.8.0_4.0.gemfile +8 -0
- data/gemfiles/version_2.8.0_4.1.gemfile +8 -0
- data/gemfiles/version_2.8.0_4.2.gemfile +8 -0
- data/gemfiles/version_2.8.0_5.0.gemfile +8 -0
- data/gemfiles/version_2.8.0_5.1.gemfile +8 -0
- data/json-schema_builder.gemspec +1 -1
- data/lib/json/schema_builder/array.rb +1 -0
- data/lib/json/schema_builder/entity.rb +22 -5
- data/lib/json/schema_builder/schema.rb +23 -3
- data/lib/json/schema_builder/validation.rb +27 -1
- data/lib/json/schema_builder/version.rb +1 -1
- data/lib/json/schema_builder.rb +1 -1
- data/spec/integration/custom_errors_spec.rb +36 -0
- data/spec/support/examples/custom_errors.rb +48 -0
- data/spec/support/shared_contexts_for_entity.rb +1 -1
- data/spec/unit/entity_spec.rb +1 -1
- data/spec/unit/schema_spec.rb +228 -48
- metadata +48 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7e1e931da1f8e1ef88c5f267408422b8195f7d85
|
|
4
|
+
data.tar.gz: 561d28974eb9bcaa95d84c3799db95ea466ee3b1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: de361202331e17c8b447fda6f5d76de261edef07f367af44493ef4bd1034c040e97a4efbd7c865ed18bd33ef10316bd42543d74d34be1ff6c6b907bf4aa018f7
|
|
7
|
+
data.tar.gz: 0d23b47272718d8ca60b575ed39b10c562af101d7537e2b27e064ef8ea4ef87cb6b5822a9eedc65cc1deb8a93f24b555373048a8c68bf4a05671d97f2fab0814
|
data/.travis.yml
CHANGED
|
@@ -9,8 +9,43 @@ addons:
|
|
|
9
9
|
repo_token:
|
|
10
10
|
secure: X3mDel/6C4d8uSeaKgxA2YP4Oen5N2iklmi2mH1XzK3UihzlNKcQLxYC6IMTTfYiPlLu1BTO1KTElUqWIigpHxAAJj/Lb48S8mvKFAsmv48tOP5LaTeFNdnJA49k0hCXQbItlyVBmUhEtkdyelLciP3ygcKgEcR/jZGcJM/aZBY=
|
|
11
11
|
gemfile:
|
|
12
|
-
- gemfiles/
|
|
13
|
-
- gemfiles/
|
|
14
|
-
- gemfiles/
|
|
15
|
-
- gemfiles/
|
|
16
|
-
- gemfiles/
|
|
12
|
+
- gemfiles/version_2.1.0_4.0.gemfile
|
|
13
|
+
- gemfiles/version_2.1.0_4.1.gemfile
|
|
14
|
+
- gemfiles/version_2.1.0_4.2.gemfile
|
|
15
|
+
- gemfiles/version_2.1.0_5.0.gemfile
|
|
16
|
+
- gemfiles/version_2.1.0_5.1.gemfile
|
|
17
|
+
- gemfiles/version_2.2.0_4.0.gemfile
|
|
18
|
+
- gemfiles/version_2.2.0_4.1.gemfile
|
|
19
|
+
- gemfiles/version_2.2.0_4.2.gemfile
|
|
20
|
+
- gemfiles/version_2.2.0_5.0.gemfile
|
|
21
|
+
- gemfiles/version_2.2.0_5.1.gemfile
|
|
22
|
+
- gemfiles/version_2.3.0_4.0.gemfile
|
|
23
|
+
- gemfiles/version_2.3.0_4.1.gemfile
|
|
24
|
+
- gemfiles/version_2.3.0_4.2.gemfile
|
|
25
|
+
- gemfiles/version_2.3.0_5.0.gemfile
|
|
26
|
+
- gemfiles/version_2.3.0_5.1.gemfile
|
|
27
|
+
- gemfiles/version_2.4.0_4.0.gemfile
|
|
28
|
+
- gemfiles/version_2.4.0_4.1.gemfile
|
|
29
|
+
- gemfiles/version_2.4.0_4.2.gemfile
|
|
30
|
+
- gemfiles/version_2.4.0_5.0.gemfile
|
|
31
|
+
- gemfiles/version_2.4.0_5.1.gemfile
|
|
32
|
+
- gemfiles/version_2.5.0_4.0.gemfile
|
|
33
|
+
- gemfiles/version_2.5.0_4.1.gemfile
|
|
34
|
+
- gemfiles/version_2.5.0_4.2.gemfile
|
|
35
|
+
- gemfiles/version_2.5.0_5.0.gemfile
|
|
36
|
+
- gemfiles/version_2.5.0_5.1.gemfile
|
|
37
|
+
- gemfiles/version_2.6.0_4.0.gemfile
|
|
38
|
+
- gemfiles/version_2.6.0_4.1.gemfile
|
|
39
|
+
- gemfiles/version_2.6.0_4.2.gemfile
|
|
40
|
+
- gemfiles/version_2.6.0_5.0.gemfile
|
|
41
|
+
- gemfiles/version_2.6.0_5.1.gemfile
|
|
42
|
+
- gemfiles/version_2.7.0_4.0.gemfile
|
|
43
|
+
- gemfiles/version_2.7.0_4.1.gemfile
|
|
44
|
+
- gemfiles/version_2.7.0_4.2.gemfile
|
|
45
|
+
- gemfiles/version_2.7.0_5.0.gemfile
|
|
46
|
+
- gemfiles/version_2.7.0_5.1.gemfile
|
|
47
|
+
- gemfiles/version_2.8.0_4.0.gemfile
|
|
48
|
+
- gemfiles/version_2.8.0_4.1.gemfile
|
|
49
|
+
- gemfiles/version_2.8.0_4.2.gemfile
|
|
50
|
+
- gemfiles/version_2.8.0_5.0.gemfile
|
|
51
|
+
- gemfiles/version_2.8.0_5.1.gemfile
|
data/Appraisals
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
%w(
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
%w(2.1.0 2.2.0 2.3.0 2.4.0 2.5.0 2.6.0 2.7.0 2.8.0).each do |json_schema_version|
|
|
2
|
+
%w(4.0 4.1 4.2 5.0 5.1).each do |active_support_version|
|
|
3
|
+
appraise "version-#{json_schema_version}-#{active_support_version}" do
|
|
4
|
+
gem "json-schema", "~> #{json_schema_version}"
|
|
5
|
+
gem "activesupport", "~> #{active_support_version}"
|
|
6
|
+
end
|
|
4
7
|
end
|
|
5
8
|
end
|
data/json-schema_builder.gemspec
CHANGED
|
@@ -25,5 +25,5 @@ Gem::Specification.new do |spec|
|
|
|
25
25
|
spec.add_development_dependency 'pry-byebug'
|
|
26
26
|
spec.add_development_dependency 'appraisal'
|
|
27
27
|
spec.add_dependency 'activesupport', '>= 4.0'
|
|
28
|
-
spec.add_dependency 'json-schema', '>= 2'
|
|
28
|
+
spec.add_dependency 'json-schema', '>= 2.1'
|
|
29
29
|
end
|
|
@@ -12,7 +12,7 @@ module JSON
|
|
|
12
12
|
include Validation
|
|
13
13
|
include Helpers
|
|
14
14
|
class_attribute :registered_type
|
|
15
|
-
attr_accessor :name, :parent, :children, :options
|
|
15
|
+
attr_accessor :name, :parent, :children, :options, :fragment, :fragments, :error
|
|
16
16
|
|
|
17
17
|
attribute :title
|
|
18
18
|
attribute :description
|
|
@@ -30,19 +30,30 @@ module JSON
|
|
|
30
30
|
def initialize(name, opts = { }, &block)
|
|
31
31
|
@name = name
|
|
32
32
|
@children = []
|
|
33
|
+
@fragments = Hash.new { |hash, key| hash[key] = ::Array.new }
|
|
34
|
+
@fragments["#/"] << self if opts[:root]
|
|
33
35
|
self.type = self.class.registered_type
|
|
34
36
|
initialize_parent_with opts
|
|
35
37
|
initialize_with opts
|
|
36
38
|
eval_block &block
|
|
37
39
|
end
|
|
38
40
|
|
|
41
|
+
def add_fragment(child)
|
|
42
|
+
@fragments[child.fragment] << child
|
|
43
|
+
@parent.add_fragment(child) if @parent
|
|
44
|
+
end
|
|
45
|
+
|
|
39
46
|
def schema
|
|
40
|
-
@schema ||= Schema.new
|
|
47
|
+
@schema ||= Schema.new({}, self)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def required
|
|
51
|
+
schema["required"] || []
|
|
41
52
|
end
|
|
42
53
|
|
|
43
54
|
def required=(*values)
|
|
44
|
-
@parent.required ||= []
|
|
45
|
-
@parent.required << @name
|
|
55
|
+
@parent.schema["required"] ||= []
|
|
56
|
+
@parent.schema["required"] << @name
|
|
46
57
|
end
|
|
47
58
|
|
|
48
59
|
def merge_children!
|
|
@@ -75,7 +86,13 @@ module JSON
|
|
|
75
86
|
|
|
76
87
|
def initialize_parent_with(opts)
|
|
77
88
|
@parent = opts.delete :parent
|
|
78
|
-
|
|
89
|
+
if parent
|
|
90
|
+
@fragment = [@parent.fragment, name].compact.join("/").gsub(%r(//), "/")
|
|
91
|
+
parent.children << self
|
|
92
|
+
parent.add_fragment(self)
|
|
93
|
+
else
|
|
94
|
+
@fragment = "#/"
|
|
95
|
+
end
|
|
79
96
|
end
|
|
80
97
|
|
|
81
98
|
def initialize_with(opts)
|
|
@@ -1,19 +1,39 @@
|
|
|
1
|
+
require_relative "validation"
|
|
2
|
+
|
|
1
3
|
module JSON
|
|
2
4
|
module SchemaBuilder
|
|
3
5
|
class Schema
|
|
4
|
-
|
|
6
|
+
include Validation
|
|
7
|
+
|
|
8
|
+
attr_accessor :data, :entities
|
|
5
9
|
delegate :[], :[]=, :to_h, :as_json, to: :data
|
|
6
10
|
|
|
7
|
-
def initialize(hash = {})
|
|
11
|
+
def initialize(hash = {}, entities = nil)
|
|
8
12
|
@data = hash.with_indifferent_access
|
|
13
|
+
@entities = Array(entities)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def options
|
|
17
|
+
JSON::SchemaBuilder.options.to_h
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def fragments
|
|
21
|
+
fragment_map = Hash.new { |hash, key| hash[key] = [] }
|
|
22
|
+
entities.map(&:fragments).each do |entity_fragments|
|
|
23
|
+
entity_fragments.each do |fragment, entity|
|
|
24
|
+
fragment_map[fragment] += entity
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
fragment_map
|
|
9
28
|
end
|
|
10
29
|
|
|
11
30
|
def merge(schema)
|
|
12
|
-
self.class.new _deep_merge(data, schema.data)
|
|
31
|
+
self.class.new _deep_merge(data, schema.data), entities + schema.entities
|
|
13
32
|
end
|
|
14
33
|
|
|
15
34
|
def merge!(schema)
|
|
16
35
|
@data = _deep_merge(data, schema.data)
|
|
36
|
+
@entities += schema.entities
|
|
17
37
|
self
|
|
18
38
|
end
|
|
19
39
|
|
|
@@ -19,7 +19,33 @@ module JSON
|
|
|
19
19
|
|
|
20
20
|
def _validate(validator, data, opts)
|
|
21
21
|
opts.reverse_merge! options if options
|
|
22
|
-
|
|
22
|
+
customize_errors = opts.delete(:customize_errors)
|
|
23
|
+
opts[:errors_as_objects] = true if customize_errors
|
|
24
|
+
validation_errors = JSON::Validator.send validator, as_json, data, opts
|
|
25
|
+
customize_errors ? _customize_errors(validation_errors) : validation_errors
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def _customize_errors(error_objects)
|
|
29
|
+
_flatten_errors(error_objects).each do |error|
|
|
30
|
+
entities = Array(fragments[error[:fragment]]).select(&:error)
|
|
31
|
+
entities.each do |entity|
|
|
32
|
+
handler = entity.error
|
|
33
|
+
case handler
|
|
34
|
+
when ::Proc
|
|
35
|
+
handler.call(entities, error)
|
|
36
|
+
when ::String
|
|
37
|
+
error[:message] = entity.error
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def _flatten_errors(error_objects)
|
|
44
|
+
error_objects.map do |error_object|
|
|
45
|
+
sub_errors = error_object.delete(:errors) || []
|
|
46
|
+
sub_errors = sub_errors.values.flatten if sub_errors.is_a?(Hash)
|
|
47
|
+
[error_object, _flatten_errors(sub_errors)]
|
|
48
|
+
end.flatten
|
|
23
49
|
end
|
|
24
50
|
end
|
|
25
51
|
end
|
data/lib/json/schema_builder.rb
CHANGED
|
@@ -12,10 +12,10 @@ module JSON
|
|
|
12
12
|
module SchemaBuilder
|
|
13
13
|
extend ActiveSupport::Concern
|
|
14
14
|
include DSL
|
|
15
|
-
include Helpers
|
|
16
15
|
extend JSON::SchemaBuilder::Configuration
|
|
17
16
|
|
|
18
17
|
included do |klass|
|
|
18
|
+
include Helpers
|
|
19
19
|
extend JSON::SchemaBuilder::Configuration
|
|
20
20
|
class << self
|
|
21
21
|
attr_accessor :root_key
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe Examples::CustomErrors, type: :integration do
|
|
4
|
+
let(:klass) { described_class.new({}) }
|
|
5
|
+
|
|
6
|
+
it "customizes with a proc" do
|
|
7
|
+
errors = schema.fully_validate({ user: "123", settings: { name: 456 } }, customize_errors: true)
|
|
8
|
+
expect(errors).to include hash_including(message: "Custom object error")
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "customizes with a string" do
|
|
12
|
+
errors = schema.fully_validate({ settings: { name: 456 } }, customize_errors: true)
|
|
13
|
+
expect(errors).to include hash_including(message: "Custom name error")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "customizes required errors" do
|
|
17
|
+
errors = schema.fully_validate({ settings: { } }, customize_errors: true)
|
|
18
|
+
expect(errors).to include hash_including(message: %q(#/ requires properties ["user"]))
|
|
19
|
+
expect(errors).to include hash_including(message: %q(#/settings requires properties ["name"]))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "merges error handlers" do
|
|
23
|
+
schema = klass.example.schema.merge(klass.example2.schema)
|
|
24
|
+
errors = schema.fully_validate({ settings: { other: 123 } }, customize_errors: true)
|
|
25
|
+
expect(errors).to include hash_including(message: "Other error")
|
|
26
|
+
expect(errors).to include hash_including(message: %q(#/ requires properties ["user"]))
|
|
27
|
+
expect(errors).to include hash_including(message: %q(#/settings requires properties ["name", "other"]))
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "flattens nested errors" do
|
|
31
|
+
schema = klass.any_of
|
|
32
|
+
errors = schema.fully_validate({ user: { settings: { name: 123 } }}, customize_errors: true)
|
|
33
|
+
expect(errors.length).to eq(3)
|
|
34
|
+
expect(errors).to include hash_including(message: "Nested")
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module Examples
|
|
2
|
+
class CustomErrors
|
|
3
|
+
include JSON::SchemaBuilder
|
|
4
|
+
|
|
5
|
+
def required_error
|
|
6
|
+
lambda do |entities, error|
|
|
7
|
+
if error[:failed_attribute] == "Required"
|
|
8
|
+
required = entities.map(&:required).inject(:+).uniq
|
|
9
|
+
error[:message] = "#{error[:fragment]} requires properties #{required.map(&:to_s).inspect}"
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def object_error
|
|
15
|
+
lambda do |entities, error|
|
|
16
|
+
error[:message] = "Custom object error"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def example
|
|
21
|
+
object error: required_error do
|
|
22
|
+
object :user, required: true, error: object_error
|
|
23
|
+
object :settings, error: required_error do
|
|
24
|
+
string :name, required: true, error: "Custom name error"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def example2
|
|
30
|
+
object do
|
|
31
|
+
object :settings, error: required_error do
|
|
32
|
+
string :other, required: true, error: "Other error"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def any_of
|
|
38
|
+
object do
|
|
39
|
+
entity :user do
|
|
40
|
+
any_of [
|
|
41
|
+
object { object(:settings) { string :name, error: "Nested" } },
|
|
42
|
+
null
|
|
43
|
+
]
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -15,7 +15,7 @@ RSpec.shared_context 'an entity' do
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
RSpec.shared_context 'an entity with a parent' do
|
|
18
|
-
let(:parent){
|
|
18
|
+
let(:parent){ JSON::SchemaBuilder::Entity.new 'parent' }
|
|
19
19
|
subject do
|
|
20
20
|
JSON::SchemaBuilder::Entity.new 'name', title: 'test', parent: parent do
|
|
21
21
|
schema[:evaluated_block] = true
|
data/spec/unit/entity_spec.rb
CHANGED
data/spec/unit/schema_spec.rb
CHANGED
|
@@ -1,66 +1,149 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
RSpec.describe JSON::SchemaBuilder::Schema, type: :unit do
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
4
|
+
subject(:schema) do
|
|
5
|
+
Class.new do
|
|
6
|
+
include JSON::SchemaBuilder
|
|
7
|
+
|
|
8
|
+
def example
|
|
9
|
+
object do
|
|
10
|
+
integer :a
|
|
11
|
+
|
|
12
|
+
object :b do
|
|
13
|
+
integer :c
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
array :array do
|
|
17
|
+
items do
|
|
18
|
+
object do
|
|
19
|
+
integer :foo
|
|
20
|
+
|
|
21
|
+
object :bar do
|
|
22
|
+
integer :baz
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
entity :anything do
|
|
29
|
+
any_of [
|
|
30
|
+
null,
|
|
31
|
+
string,
|
|
32
|
+
object {
|
|
33
|
+
string :one
|
|
34
|
+
string :two
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end.new.example.schema
|
|
16
41
|
end
|
|
17
42
|
|
|
18
43
|
let(:other) do
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
44
|
+
Class.new do
|
|
45
|
+
include JSON::SchemaBuilder
|
|
46
|
+
|
|
47
|
+
def example
|
|
48
|
+
object do
|
|
49
|
+
integer :a2
|
|
50
|
+
|
|
51
|
+
object :b do
|
|
52
|
+
integer :d
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
array :array do
|
|
56
|
+
items do
|
|
57
|
+
object do
|
|
58
|
+
object :bar do
|
|
59
|
+
integer :qux
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
entity :anything do
|
|
66
|
+
any_of [
|
|
67
|
+
null,
|
|
68
|
+
object {
|
|
69
|
+
string :two
|
|
70
|
+
string :three
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end.new.example.schema
|
|
29
77
|
end
|
|
30
78
|
|
|
31
79
|
let(:merged) do
|
|
32
80
|
{
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
},
|
|
38
|
-
"array" => [
|
|
39
|
-
123, {
|
|
40
|
-
"foo" => 1,
|
|
41
|
-
"bar" => {
|
|
42
|
-
"baz" => 0,
|
|
43
|
-
}
|
|
81
|
+
"type" => :object,
|
|
82
|
+
"properties" => {
|
|
83
|
+
"a" => {
|
|
84
|
+
"type" => "integer"
|
|
44
85
|
},
|
|
45
|
-
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
],
|
|
52
|
-
"anyOf" => [
|
|
53
|
-
{ "type" => "null" },
|
|
54
|
-
{ "type" => "string" },
|
|
55
|
-
{
|
|
86
|
+
"a2" => {
|
|
87
|
+
"type" => "integer"
|
|
88
|
+
},
|
|
89
|
+
"b" => {
|
|
56
90
|
"type" => "object",
|
|
57
91
|
"properties" => {
|
|
58
|
-
"
|
|
59
|
-
|
|
60
|
-
|
|
92
|
+
"c" => {
|
|
93
|
+
"type" => "integer"
|
|
94
|
+
},
|
|
95
|
+
"d" => {
|
|
96
|
+
"type" => "integer"
|
|
97
|
+
}
|
|
61
98
|
}
|
|
99
|
+
},
|
|
100
|
+
"array" => {
|
|
101
|
+
"type" => "array",
|
|
102
|
+
"items" => {
|
|
103
|
+
"type" => "object",
|
|
104
|
+
"properties" => {
|
|
105
|
+
"foo" => {
|
|
106
|
+
"type" => "integer",
|
|
107
|
+
},
|
|
108
|
+
"bar" => {
|
|
109
|
+
"type" => "object",
|
|
110
|
+
"properties" => {
|
|
111
|
+
"baz" => {
|
|
112
|
+
"type" => "integer"
|
|
113
|
+
},
|
|
114
|
+
"qux" => {
|
|
115
|
+
"type" => "integer"
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
"anything" => {
|
|
123
|
+
"anyOf" => [
|
|
124
|
+
{
|
|
125
|
+
"type" => "null"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"type" => "string"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"type" => "object",
|
|
132
|
+
"properties" => {
|
|
133
|
+
"one" => {
|
|
134
|
+
"type" => "string"
|
|
135
|
+
},
|
|
136
|
+
"two" => {
|
|
137
|
+
"type" => "string"
|
|
138
|
+
},
|
|
139
|
+
"three" => {
|
|
140
|
+
"type" => "string"
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
]
|
|
62
145
|
}
|
|
63
|
-
|
|
146
|
+
}
|
|
64
147
|
}
|
|
65
148
|
end
|
|
66
149
|
|
|
@@ -93,4 +176,101 @@ RSpec.describe JSON::SchemaBuilder::Schema, type: :unit do
|
|
|
93
176
|
expect{ schema.merge! other }.to_not change { other.data }
|
|
94
177
|
end
|
|
95
178
|
end
|
|
179
|
+
|
|
180
|
+
%w(validate validate! fully_validate).each do |validator|
|
|
181
|
+
describe "##{ validator }" do
|
|
182
|
+
it "should #{ validator }" do
|
|
183
|
+
expect(JSON::Validator).to receive(validator)
|
|
184
|
+
.with schema.as_json, { }, opts: true
|
|
185
|
+
schema.send validator, { }, opts: true
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
describe "#fragments" do
|
|
191
|
+
context "with an unmerged schema" do
|
|
192
|
+
subject(:fragments) { schema.fragments }
|
|
193
|
+
its(:keys) do
|
|
194
|
+
is_expected.to match_array %w(
|
|
195
|
+
#/
|
|
196
|
+
#/a
|
|
197
|
+
#/b
|
|
198
|
+
#/b/c
|
|
199
|
+
#/array
|
|
200
|
+
#/array/foo
|
|
201
|
+
#/array/bar
|
|
202
|
+
#/array/bar/baz
|
|
203
|
+
#/anything
|
|
204
|
+
#/anything/one
|
|
205
|
+
#/anything/two
|
|
206
|
+
)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
it "stores the schema by fragment" do
|
|
210
|
+
expect(fragments["#/"].first.as_json).to eq schema.as_json
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
it "structures the fragments correctly" do
|
|
214
|
+
expect(fragments.values.flatten).to all be_a JSON::SchemaBuilder::Entity
|
|
215
|
+
expect(fragments["#/"].length).to eq 1
|
|
216
|
+
expect(fragments["#/"].length).to eq 1
|
|
217
|
+
expect(fragments["#/a"].length).to eq 1
|
|
218
|
+
expect(fragments["#/b"].length).to eq 1
|
|
219
|
+
expect(fragments["#/b/c"].length).to eq 1
|
|
220
|
+
expect(fragments["#/array"].length).to eq 3
|
|
221
|
+
expect(fragments["#/array/foo"].length).to eq 1
|
|
222
|
+
expect(fragments["#/array/bar"].length).to eq 1
|
|
223
|
+
expect(fragments["#/array/bar/baz"].length).to eq 1
|
|
224
|
+
expect(fragments["#/anything"].length).to eq 4
|
|
225
|
+
expect(fragments["#/anything/one"].length).to eq 1
|
|
226
|
+
expect(fragments["#/anything/two"].length).to eq 1
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
context "with a merged schema" do
|
|
231
|
+
subject(:fragments) { schema.merge(other).fragments }
|
|
232
|
+
its(:keys) do
|
|
233
|
+
is_expected.to match_array %w(
|
|
234
|
+
#/
|
|
235
|
+
#/a
|
|
236
|
+
#/a2
|
|
237
|
+
#/b
|
|
238
|
+
#/b/c
|
|
239
|
+
#/b/d
|
|
240
|
+
#/array
|
|
241
|
+
#/array/foo
|
|
242
|
+
#/array/bar
|
|
243
|
+
#/array/bar/baz
|
|
244
|
+
#/array/bar/qux
|
|
245
|
+
#/anything
|
|
246
|
+
#/anything/one
|
|
247
|
+
#/anything/two
|
|
248
|
+
#/anything/three
|
|
249
|
+
)
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
it "stores the schema by fragment" do
|
|
253
|
+
expect(fragments["#/"].first.as_json).to eq schema.as_json
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
it "structures the fragments correctly" do
|
|
257
|
+
expect(fragments.values.flatten).to all be_a JSON::SchemaBuilder::Entity
|
|
258
|
+
expect(fragments["#/"].length).to eq 2
|
|
259
|
+
expect(fragments["#/a"].length).to eq 1
|
|
260
|
+
expect(fragments["#/a2"].length).to eq 1
|
|
261
|
+
expect(fragments["#/b"].length).to eq 2
|
|
262
|
+
expect(fragments["#/b/c"].length).to eq 1
|
|
263
|
+
expect(fragments["#/b/d"].length).to eq 1
|
|
264
|
+
expect(fragments["#/array"].length).to eq 6
|
|
265
|
+
expect(fragments["#/array/foo"].length).to eq 1
|
|
266
|
+
expect(fragments["#/array/bar"].length).to eq 2
|
|
267
|
+
expect(fragments["#/array/bar/baz"].length).to eq 1
|
|
268
|
+
expect(fragments["#/array/bar/qux"].length).to eq 1
|
|
269
|
+
expect(fragments["#/anything"].length).to eq 7
|
|
270
|
+
expect(fragments["#/anything/one"].length).to eq 1
|
|
271
|
+
expect(fragments["#/anything/two"].length).to eq 2
|
|
272
|
+
expect(fragments["#/anything/three"].length).to eq 1
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
end
|
|
96
276
|
end
|
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.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Michael Parrish
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2018-01-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -114,14 +114,14 @@ dependencies:
|
|
|
114
114
|
requirements:
|
|
115
115
|
- - ">="
|
|
116
116
|
- !ruby/object:Gem::Version
|
|
117
|
-
version: '2'
|
|
117
|
+
version: '2.1'
|
|
118
118
|
type: :runtime
|
|
119
119
|
prerelease: false
|
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
|
121
121
|
requirements:
|
|
122
122
|
- - ">="
|
|
123
123
|
- !ruby/object:Gem::Version
|
|
124
|
-
version: '2'
|
|
124
|
+
version: '2.1'
|
|
125
125
|
description: Build JSON schemas with Ruby
|
|
126
126
|
email:
|
|
127
127
|
- michael@zooniverse.org
|
|
@@ -139,11 +139,46 @@ files:
|
|
|
139
139
|
- README.md
|
|
140
140
|
- Rakefile
|
|
141
141
|
- gemfiles/.bundle/config
|
|
142
|
-
- gemfiles/
|
|
143
|
-
- gemfiles/
|
|
144
|
-
- gemfiles/
|
|
145
|
-
- gemfiles/
|
|
146
|
-
- gemfiles/
|
|
142
|
+
- gemfiles/version_2.1.0_4.0.gemfile
|
|
143
|
+
- gemfiles/version_2.1.0_4.1.gemfile
|
|
144
|
+
- gemfiles/version_2.1.0_4.2.gemfile
|
|
145
|
+
- gemfiles/version_2.1.0_5.0.gemfile
|
|
146
|
+
- gemfiles/version_2.1.0_5.1.gemfile
|
|
147
|
+
- gemfiles/version_2.2.0_4.0.gemfile
|
|
148
|
+
- gemfiles/version_2.2.0_4.1.gemfile
|
|
149
|
+
- gemfiles/version_2.2.0_4.2.gemfile
|
|
150
|
+
- gemfiles/version_2.2.0_5.0.gemfile
|
|
151
|
+
- gemfiles/version_2.2.0_5.1.gemfile
|
|
152
|
+
- gemfiles/version_2.3.0_4.0.gemfile
|
|
153
|
+
- gemfiles/version_2.3.0_4.1.gemfile
|
|
154
|
+
- gemfiles/version_2.3.0_4.2.gemfile
|
|
155
|
+
- gemfiles/version_2.3.0_5.0.gemfile
|
|
156
|
+
- gemfiles/version_2.3.0_5.1.gemfile
|
|
157
|
+
- gemfiles/version_2.4.0_4.0.gemfile
|
|
158
|
+
- gemfiles/version_2.4.0_4.1.gemfile
|
|
159
|
+
- gemfiles/version_2.4.0_4.2.gemfile
|
|
160
|
+
- gemfiles/version_2.4.0_5.0.gemfile
|
|
161
|
+
- gemfiles/version_2.4.0_5.1.gemfile
|
|
162
|
+
- gemfiles/version_2.5.0_4.0.gemfile
|
|
163
|
+
- gemfiles/version_2.5.0_4.1.gemfile
|
|
164
|
+
- gemfiles/version_2.5.0_4.2.gemfile
|
|
165
|
+
- gemfiles/version_2.5.0_5.0.gemfile
|
|
166
|
+
- gemfiles/version_2.5.0_5.1.gemfile
|
|
167
|
+
- gemfiles/version_2.6.0_4.0.gemfile
|
|
168
|
+
- gemfiles/version_2.6.0_4.1.gemfile
|
|
169
|
+
- gemfiles/version_2.6.0_4.2.gemfile
|
|
170
|
+
- gemfiles/version_2.6.0_5.0.gemfile
|
|
171
|
+
- gemfiles/version_2.6.0_5.1.gemfile
|
|
172
|
+
- gemfiles/version_2.7.0_4.0.gemfile
|
|
173
|
+
- gemfiles/version_2.7.0_4.1.gemfile
|
|
174
|
+
- gemfiles/version_2.7.0_4.2.gemfile
|
|
175
|
+
- gemfiles/version_2.7.0_5.0.gemfile
|
|
176
|
+
- gemfiles/version_2.7.0_5.1.gemfile
|
|
177
|
+
- gemfiles/version_2.8.0_4.0.gemfile
|
|
178
|
+
- gemfiles/version_2.8.0_4.1.gemfile
|
|
179
|
+
- gemfiles/version_2.8.0_4.2.gemfile
|
|
180
|
+
- gemfiles/version_2.8.0_5.0.gemfile
|
|
181
|
+
- gemfiles/version_2.8.0_5.1.gemfile
|
|
147
182
|
- json-schema_builder.gemspec
|
|
148
183
|
- lib/json/schema_builder.rb
|
|
149
184
|
- lib/json/schema_builder/any.rb
|
|
@@ -168,6 +203,7 @@ files:
|
|
|
168
203
|
- lib/json/schema_builder/version.rb
|
|
169
204
|
- spec/integration/array_definitions_spec.rb
|
|
170
205
|
- spec/integration/context_delegation_spec.rb
|
|
206
|
+
- spec/integration/custom_errors_spec.rb
|
|
171
207
|
- spec/integration/entity_literals_spec.rb
|
|
172
208
|
- spec/integration/ids_spec.rb
|
|
173
209
|
- spec/integration/mixed_arrays_spec.rb
|
|
@@ -186,6 +222,7 @@ files:
|
|
|
186
222
|
- spec/support/attribute_matcher.rb
|
|
187
223
|
- spec/support/examples/array_definitions.rb
|
|
188
224
|
- spec/support/examples/context_delegation.rb
|
|
225
|
+
- spec/support/examples/custom_errors.rb
|
|
189
226
|
- spec/support/examples/entity_literals.rb
|
|
190
227
|
- spec/support/examples/ids.rb
|
|
191
228
|
- spec/support/examples/mixed_arrays.rb
|
|
@@ -240,6 +277,7 @@ summary: Build JSON schemas with Ruby
|
|
|
240
277
|
test_files:
|
|
241
278
|
- spec/integration/array_definitions_spec.rb
|
|
242
279
|
- spec/integration/context_delegation_spec.rb
|
|
280
|
+
- spec/integration/custom_errors_spec.rb
|
|
243
281
|
- spec/integration/entity_literals_spec.rb
|
|
244
282
|
- spec/integration/ids_spec.rb
|
|
245
283
|
- spec/integration/mixed_arrays_spec.rb
|
|
@@ -258,6 +296,7 @@ test_files:
|
|
|
258
296
|
- spec/support/attribute_matcher.rb
|
|
259
297
|
- spec/support/examples/array_definitions.rb
|
|
260
298
|
- spec/support/examples/context_delegation.rb
|
|
299
|
+
- spec/support/examples/custom_errors.rb
|
|
261
300
|
- spec/support/examples/entity_literals.rb
|
|
262
301
|
- spec/support/examples/ids.rb
|
|
263
302
|
- spec/support/examples/mixed_arrays.rb
|