jsi 0.0.2 → 0.0.3

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
  SHA256:
3
- metadata.gz: 61dd1e2dc8c145ccf5acdcd6a0d6eaeef0d61dd85e876347af89f7168e838319
4
- data.tar.gz: de6f01e5e859f2b3039b7d2c6f734b1e30b97b8c946f2444783581931d5939e9
3
+ metadata.gz: 12a262c5b9ec6c22d16c8e4f5cb983c92266d165964a120ffcd72f7e0bd877d1
4
+ data.tar.gz: 3e4671dda156d3d8073e9f7af42e3335af8f3482719a0495d4f57a2dfaaf12c9
5
5
  SHA512:
6
- metadata.gz: c15c232306814b19a3b84f94c9bd5bacfa261c7124e007ad8961e6e7a28495c23e675963aca024d2abb29613ba9092313cf11b0344feb3e20f38dec6dcf511b1
7
- data.tar.gz: c00160e62da570c862b694d516bb157019b1799dcff24f594f494fa695c45fcfaa4a5e34e93b8bf35978c28e9bf13e84ed86b3938eff3b7443c6e4cae81118af
6
+ metadata.gz: 7f9c9816756bb70c16498d2ba503c7b0148533b37ae065d8426e654a0644066db6108a6a7d79789bb039f4911432b4273ca85d6a08a47783d0e992af06e248c2
7
+ data.tar.gz: c9859fffe7cffbdde822530c828db5344cefa12e2b94eef5d3732d88dca741db5e93414c2800d681fba4555b6694d5bf873cdee08ccbfbce293f3e159ac2749e
@@ -1,3 +1,9 @@
1
+ # v0.0.3
2
+
3
+ - JSI::Base returns an instance of the default value for the schema if applicable
4
+ - JSI::Base instance method #class_for_schema may be overridden by subclasses
5
+ - bugfixes and internal refactoring
6
+
1
7
  # v0.0.2
2
8
 
3
9
  - JSI::JSON::Node and other utilities duck-type better with #to_hash and #to_ary
@@ -67,14 +67,14 @@ module JSI
67
67
  # a Node already).
68
68
  #
69
69
  # @param instance [Object] the JSON Schema instance being represented
70
- # @param origin [JSI::Base] for internal use, specifies a parent
71
- # from which this JSI originated
72
- def initialize(instance, origin: nil)
70
+ # @param ancestor [JSI::Base] for internal use, specifies an ancestor
71
+ # from which this JSI originated to calculate #parents
72
+ def initialize(instance, ancestor: nil)
73
73
  unless respond_to?(:schema)
74
74
  raise(TypeError, "cannot instantiate #{self.class.inspect} which has no method #schema. please use JSI.class_for_schema")
75
75
  end
76
76
 
77
- @origin = origin || self
77
+ @ancestor = ancestor || self
78
78
  self.instance = instance
79
79
 
80
80
  if @instance.is_a?(JSI::JSON::HashNode)
@@ -87,6 +87,9 @@ module JSI
87
87
  # the instance of the json-schema. this is a JSI::JSON::Node.
88
88
  attr_reader :instance
89
89
 
90
+ # a JSI which is an ancestor of this
91
+ attr_reader :ancestor
92
+
90
93
  # each is overridden by BaseHash or BaseArray when appropriate. the base
91
94
  # #each is not actually implemented, along with all the methods of Enumerable.
92
95
  def each
@@ -99,8 +102,8 @@ module JSI
99
102
  #
100
103
  # @return [Array<JSI::Base>]
101
104
  def parents
102
- parent = @origin
103
- (@origin.instance.path.size...self.instance.path.size).map do |i|
105
+ parent = @ancestor
106
+ (@ancestor.instance.path.size...self.instance.path.size).map do |i|
104
107
  parent.tap do
105
108
  parent = parent[self.instance.path[i]]
106
109
  end
@@ -123,7 +126,7 @@ module JSI
123
126
  if derefed.object_id == instance.object_id
124
127
  self
125
128
  else
126
- self.class.new(derefed, origin: @origin)
129
+ self.class.new(derefed, ancestor: @ancestor)
127
130
  end
128
131
  end
129
132
 
@@ -136,7 +139,7 @@ module JSI
136
139
  # @return [JSI::Base subclass the same as self] the modified copy of self
137
140
  def modified_copy(&block)
138
141
  modified_instance = instance.modified_copy(&block)
139
- self.class.new(modified_instance, origin: @origin)
142
+ self.class.new(modified_instance, ancestor: @ancestor)
140
143
  end
141
144
 
142
145
  def fragment
@@ -228,6 +231,12 @@ module JSI
228
231
  instance[subscript] = value
229
232
  end
230
233
  end
234
+
235
+ # this is an instance method in order to allow subclasses of JSI classes to
236
+ # override it to point to other subclasses corresponding to other schemas.
237
+ def class_for_schema(schema)
238
+ JSI.class_for_schema(schema)
239
+ end
231
240
  end
232
241
 
233
242
  # this module is just a namespace for schema classes.
@@ -247,13 +256,7 @@ module JSI
247
256
 
248
257
  # see {JSI.class_for_schema}
249
258
  def SchemaClasses.class_for_schema(schema_object)
250
- if schema_object.is_a?(JSI::Schema)
251
- schema__ = schema_object
252
- else
253
- schema__ = JSI::Schema.new(schema_object)
254
- end
255
-
256
- memoize(:class_for_schema, schema__) do |schema_|
259
+ memoize(:class_for_schema, JSI::Schema.from_object(schema_object)) do |schema_|
257
260
  begin
258
261
  begin
259
262
  Class.new(Base).instance_exec(schema_) do |schema|
@@ -284,13 +287,7 @@ module JSI
284
287
  # class will be defined. users should use #[] and #[]= to access properties
285
288
  # whose names conflict with existing methods.
286
289
  def SchemaClasses.module_for_schema(schema_object)
287
- if schema_object.is_a?(JSI::Schema)
288
- schema__ = schema_object
289
- else
290
- schema__ = JSI::Schema.new(schema_object)
291
- end
292
-
293
- memoize(:module_for_schema, schema__) do |schema_|
290
+ memoize(:module_for_schema, JSI::Schema.from_object(schema_object)) do |schema_|
294
291
  Module.new.tap do |m|
295
292
  m.instance_exec(schema_) do |schema|
296
293
  define_method(:schema) { schema }
@@ -369,8 +366,16 @@ module JSI
369
366
  property_schema = schema.subschema_for_property(property_name)
370
367
  property_schema = property_schema && property_schema.match_to_instance(instance[property_name])
371
368
 
372
- if property_schema && instance[property_name].is_a?(JSON::Node)
373
- JSI.class_for_schema(property_schema).new(instance[property_name], origin: @origin)
369
+ if !instance.key?(property_name) && property_schema && property_schema.schema_object.key?('default')
370
+ # use the default value
371
+ default = property_schema.schema_object['default']
372
+ if default.respond_to?(:to_hash) || default.respond_to?(:to_ary)
373
+ class_for_schema(property_schema).new(default, ancestor: @ancestor)
374
+ else
375
+ default
376
+ end
377
+ elsif property_schema && (instance[property_name].respond_to?(:to_hash) || instance[property_name].respond_to?(:to_ary))
378
+ class_for_schema(property_schema).new(instance[property_name], ancestor: @ancestor)
374
379
  else
375
380
  instance[property_name]
376
381
  end
@@ -426,8 +431,16 @@ module JSI
426
431
  index_schema = schema.subschema_for_index(i)
427
432
  index_schema = index_schema && index_schema.match_to_instance(instance[i])
428
433
 
429
- if index_schema && instance[i].is_a?(JSON::Node)
430
- JSI.class_for_schema(index_schema).new(instance[i], origin: @origin)
434
+ if !instance.each_index.to_a.include?(i) && index_schema && index_schema.schema_object.key?('default')
435
+ # use the default value
436
+ default = index_schema.schema_object['default']
437
+ if default.respond_to?(:to_hash) || default.respond_to?(:to_ary)
438
+ class_for_schema(index_schema).new(default, ancestor: @ancestor)
439
+ else
440
+ default
441
+ end
442
+ elsif index_schema && (instance[i].respond_to?(:to_hash) || instance[i].respond_to?(:to_ary))
443
+ class_for_schema(index_schema).new(instance[i], ancestor: @ancestor)
431
444
  else
432
445
  instance[i]
433
446
  end
@@ -7,6 +7,16 @@ module JSI
7
7
  class Schema
8
8
  include Memoize
9
9
 
10
+ class << self
11
+ def from_object(schema_object)
12
+ if schema_object.is_a?(Schema)
13
+ schema_object
14
+ else
15
+ new(schema_object)
16
+ end
17
+ end
18
+ end
19
+
10
20
  # initializes a schema from a given JSI::Base, JSI::JSON::Node, or hash.
11
21
  # @param schema_object [JSI::Base, #to_hash] the schema
12
22
  def initialize(schema_object)
@@ -118,6 +128,7 @@ module JSI
118
128
  # matching allOf is questionable. all of the schemas must be matched but we just return the first match.
119
129
  # there isn't really a better answer with the current implementation. merging the schemas together
120
130
  # is a thought but is not practical.
131
+ instance = instance.deref if instance.is_a?(JSI::JSON::Node)
121
132
  %w(oneOf allOf anyOf).select { |k| schema_node[k].respond_to?(:to_ary) }.each do |someof_key|
122
133
  schema_node[someof_key].map(&:deref).map do |someof_node|
123
134
  someof_schema = self.class.new(someof_node)
@@ -201,6 +212,22 @@ module JSI
201
212
  end
202
213
  end
203
214
 
215
+ def default_value
216
+ if schema_node.key?('default')
217
+ if schema_node['default'].respond_to?(:to_ary) || schema_node['default'].respond_to?(:to_hash)
218
+ schema_class.new(schema_node['default'])
219
+ else
220
+ schema_node['default']
221
+ end
222
+ else
223
+ nil
224
+ end
225
+ end
226
+
227
+ def default_value?
228
+ schema_node.key?('default')
229
+ end
230
+
204
231
  # @return [Array<String>] array of schema validation error messages for
205
232
  # the given instance against this schema
206
233
  def fully_validate(instance)
@@ -79,6 +79,7 @@ module JSI
79
79
  end
80
80
  module_function :ycomb
81
81
  end
82
+ public
82
83
  extend Util
83
84
 
84
85
  module FingerprintHash
@@ -1,3 +1,3 @@
1
1
  module JSI
2
- VERSION = "0.0.2".freeze
2
+ VERSION = "0.0.3".freeze
3
3
  end
@@ -20,6 +20,61 @@ describe JSI::BaseArray do
20
20
  let(:class_for_schema) { JSI.class_for_schema(schema) }
21
21
  let(:subject) { class_for_schema.new(instance) }
22
22
 
23
+ describe '#[] with a default that is a basic type' do
24
+ let(:schema_content) do
25
+ {
26
+ 'type' => 'array',
27
+ 'items' => {'default' => 'foo'},
28
+ }
29
+ end
30
+ describe 'default value' do
31
+ let(:document) { [1] }
32
+ it 'returns the default value' do
33
+ assert_equal('foo', subject[2])
34
+ end
35
+ end
36
+ describe 'nondefault value (basic type)' do
37
+ let(:document) { ['who'] }
38
+ it 'returns the nondefault value' do
39
+ assert_equal('who', subject[0])
40
+ end
41
+ end
42
+ describe 'nondefault value (nonbasic type)' do
43
+ let(:document) { [[2]] }
44
+ it 'returns the nondefault value' do
45
+ assert_instance_of(JSI.class_for_schema(schema['items']), subject[0])
46
+ assert_equal([2], subject[0].as_json)
47
+ end
48
+ end
49
+ end
50
+ describe '#[] with a default that is a nonbasic type' do
51
+ let(:schema_content) do
52
+ {
53
+ 'type' => 'array',
54
+ 'items' => {'default' => {'foo' => 2}},
55
+ }
56
+ end
57
+ describe 'default value' do
58
+ let(:document) { [{'bar' => 3}] }
59
+ it 'returns the default value' do
60
+ assert_instance_of(JSI.class_for_schema(schema['items']), subject[1])
61
+ assert_equal({'foo' => 2}, subject[1].as_json)
62
+ end
63
+ end
64
+ describe 'nondefault value (basic type)' do
65
+ let(:document) { [true, 'who'] }
66
+ it 'returns the nondefault value' do
67
+ assert_equal('who', subject[1])
68
+ end
69
+ end
70
+ describe 'nondefault value (nonbasic type)' do
71
+ let(:document) { [true, [2]] }
72
+ it 'returns the nondefault value' do
73
+ assert_instance_of(JSI.class_for_schema(schema['items']), subject[1])
74
+ assert_equal([2], subject[1].as_json)
75
+ end
76
+ end
77
+ end
23
78
  describe 'arraylike []=' do
24
79
  it 'sets an index' do
25
80
  orig_2 = subject[2]
@@ -19,6 +19,65 @@ describe JSI::BaseHash do
19
19
  let(:class_for_schema) { JSI.class_for_schema(schema) }
20
20
  let(:subject) { class_for_schema.new(instance) }
21
21
 
22
+ describe '#[] with a default that is a basic type' do
23
+ let(:schema_content) do
24
+ {
25
+ 'type' => 'object',
26
+ 'properties' => {
27
+ 'foo' => {'default' => 'foo'},
28
+ },
29
+ }
30
+ end
31
+ describe 'default value' do
32
+ let(:document) { {'bar' => 3} }
33
+ it 'returns the default value' do
34
+ assert_equal('foo', subject.foo)
35
+ end
36
+ end
37
+ describe 'nondefault value (basic type)' do
38
+ let(:document) { {'foo' => 'who'} }
39
+ it 'returns the nondefault value' do
40
+ assert_equal('who', subject.foo)
41
+ end
42
+ end
43
+ describe 'nondefault value (nonbasic type)' do
44
+ let(:document) { {'foo' => [2]} }
45
+ it 'returns the nondefault value' do
46
+ assert_instance_of(JSI.class_for_schema(schema['properties']['foo']), subject.foo)
47
+ assert_equal([2], subject.foo.as_json)
48
+ end
49
+ end
50
+ end
51
+ describe '#[] with a default that is a nonbasic type' do
52
+ let(:schema_content) do
53
+ {
54
+ 'type' => 'object',
55
+ 'properties' => {
56
+ 'foo' => {'default' => {'foo' => 2}},
57
+ },
58
+ }
59
+ end
60
+ describe 'default value' do
61
+ let(:document) { {'bar' => 3} }
62
+ it 'returns the default value' do
63
+ assert_instance_of(JSI.class_for_schema(schema['properties']['foo']), subject.foo)
64
+ assert_equal({'foo' => 2}, subject.foo.as_json)
65
+ end
66
+ end
67
+ describe 'nondefault value (basic type)' do
68
+ let(:document) { {'foo' => 'who'} }
69
+ it 'returns the nondefault value' do
70
+ assert_equal('who', subject.foo)
71
+ end
72
+ end
73
+ describe 'nondefault value (nonbasic type)' do
74
+ let(:document) { {'foo' => [2]} }
75
+ it 'returns the nondefault value' do
76
+ assert_instance_of(JSI.class_for_schema(schema['properties']['foo']), subject.foo)
77
+ assert_equal([2], subject.foo.as_json)
78
+ end
79
+ end
80
+ end
22
81
  describe 'hashlike []=' do
23
82
  it 'sets a property' do
24
83
  orig_foo = subject['foo']
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ethan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-09-27 00:00:00.000000000 Z
11
+ date: 2019-01-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json-schema