json_schema_tools 0.1.1 → 0.1.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.
- data/Gemfile +1 -1
- data/README.md +3 -2
- data/lib/schema_tools/modules/hash.rb +49 -32
- data/lib/schema_tools/version.rb +1 -1
- data/spec/schema_tools/hash_spec.rb +44 -18
- data/spec/schema_tools/modules/attributes_spec.rb +3 -2
- metadata +4 -4
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -160,11 +160,12 @@ Rather like a namespace? Good idea, but don't forget the class or module must
|
|
160
160
|
be defined.
|
161
161
|
|
162
162
|
```ruby
|
163
|
+
module SalesKing; end
|
163
164
|
SchemaTools::KlassFactory.build namespace: SalesKing
|
164
165
|
client = SalesKing::Client.new
|
165
166
|
```
|
166
167
|
|
167
|
-
Add a custom schema reader most likely
|
168
|
+
Add a custom schema reader most likely useful in conjunction with a custom path
|
168
169
|
|
169
170
|
```ruby
|
170
171
|
reader = SchemaTools::Reader.new
|
@@ -173,9 +174,9 @@ SchemaTools::KlassFactory.build reader: reader, path: HappyPdf::Schema.path
|
|
173
174
|
|
174
175
|
## Real world examples
|
175
176
|
|
176
|
-
* [HappyPdf json schema](https://github.com/happyPDF/happypdf_json_schema) .. api gem will follow
|
177
177
|
* [DocTag ruby gem](https://github.com/docTag/doctag_rb) and [DocTag json-schema](https://github.com/docTag/doctag_json_schema)
|
178
178
|
* [SalesKing json schema](https://github.com/salesking/sk_api_schema)
|
179
|
+
* [HappyPdf json schema](https://github.com/happyPDF/happypdf_json_schema) .. api gem will follow
|
179
180
|
* .. Your UseCase here
|
180
181
|
|
181
182
|
## Test
|
@@ -48,37 +48,10 @@ module SchemaTools
|
|
48
48
|
# iterate over the defined schema fields
|
49
49
|
schema['properties'].each do |field, prop|
|
50
50
|
next if fields && !fields.include?(field)
|
51
|
-
|
52
51
|
if prop['type'] == 'array'
|
53
|
-
|
54
|
-
data[field] = [] # always set an empty array
|
55
|
-
if obj.respond_to?( field ) && rel_objects = obj.send( field )
|
56
|
-
rel_objects.each do |rel_obj|
|
57
|
-
data[field] << if prop['properties'] && prop['properties']['$ref']
|
58
|
-
#got schema describing the objects
|
59
|
-
from_schema(rel_obj, opts)
|
60
|
-
else
|
61
|
-
rel_obj
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
52
|
+
data[field] = parse_list(obj, field, prop, opts)
|
66
53
|
elsif prop['type'] == 'object' # a singular related object
|
67
|
-
|
68
|
-
data[field] = nil # always set empty val
|
69
|
-
if obj.respond_to?( field ) && rel_obj = obj.send( field )
|
70
|
-
if prop['properties'] && prop['properties']['$ref']
|
71
|
-
data[field] = from_schema(rel_obj, opts)
|
72
|
-
else
|
73
|
-
# NO recursion directly get values from related object. Does
|
74
|
-
# NOT allow deeper nesting so you MUST define an own schema to be save
|
75
|
-
data[field] = {}
|
76
|
-
prop['properties'].each do |fld, prp|
|
77
|
-
data[field][fld] = rel_obj.send(fld) if obj.respond_to?(field)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
54
|
+
data[field] = parse_object(obj, field, prop, opts)
|
82
55
|
else # a simple field is only added if the object knows it
|
83
56
|
data[field] = obj.send(field) if obj.respond_to?(field)
|
84
57
|
end
|
@@ -90,10 +63,10 @@ module SchemaTools
|
|
90
63
|
hsh
|
91
64
|
end
|
92
65
|
|
66
|
+
private
|
67
|
+
|
93
68
|
# Parse the link section of the schema by replacing {id} in urls
|
94
|
-
#
|
95
|
-
# <Array[Hash{String=>String}]>::
|
96
|
-
# <nil>:: no links present
|
69
|
+
# @return [Array<Hash{String=>String}> | Nil]
|
97
70
|
def parse_links(obj, schema)
|
98
71
|
links = []
|
99
72
|
schema['links'] && schema['links'].each do |link|
|
@@ -104,6 +77,50 @@ module SchemaTools
|
|
104
77
|
links.empty? ? nil : links
|
105
78
|
end
|
106
79
|
|
80
|
+
# Parse a nested array property.
|
81
|
+
# @param [Object] obj the object in question
|
82
|
+
# @param [String] field name
|
83
|
+
# @param [Hash] prop fields schema properties
|
84
|
+
# @param [Hash] opts to_schema options
|
85
|
+
# @return [Array<Hash{String=>String}>]
|
86
|
+
def parse_list(obj, field, prop, opts)
|
87
|
+
res = []
|
88
|
+
if obj.respond_to?( field ) && rel_objects = obj.send( field )
|
89
|
+
rel_objects.each do |rel_obj|
|
90
|
+
res << if prop['properties'] && prop['properties']['$ref']
|
91
|
+
#got schema describing the objects
|
92
|
+
from_schema(rel_obj, opts)
|
93
|
+
else
|
94
|
+
rel_obj
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
res
|
99
|
+
end
|
100
|
+
|
101
|
+
# Parse a nested object property.
|
102
|
+
# @param [Object] obj the object in question
|
103
|
+
# @param [String] field name
|
104
|
+
# @param [Hash] prop fields schema properties
|
105
|
+
# @param [Hash] opts to_schema options
|
106
|
+
# @return [Array<Hash{String=>String}>]
|
107
|
+
def parse_object(obj, field, prop, opts)
|
108
|
+
res = nil
|
109
|
+
if obj.respond_to?( field ) && rel_obj = obj.send( field )
|
110
|
+
if prop['properties'] && prop['properties']['$ref']
|
111
|
+
res = from_schema(rel_obj, opts)
|
112
|
+
else
|
113
|
+
# NO recursion directly get values from related object. Does
|
114
|
+
# NOT allow deeper nesting so you MUST define an own schema to be save
|
115
|
+
res = { }
|
116
|
+
prop['properties'].each do |fld, prp|
|
117
|
+
res[fld] = rel_obj.send(fld) if rel_obj.respond_to?(fld)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
res
|
122
|
+
end
|
123
|
+
|
107
124
|
end
|
108
125
|
end
|
109
126
|
end
|
data/lib/schema_tools/version.rb
CHANGED
@@ -1,50 +1,77 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
class
|
3
|
+
class Contact
|
4
4
|
attr_accessor :first_name, :last_name, :addresses, :id
|
5
|
-
|
5
|
+
end
|
6
6
|
|
7
7
|
describe SchemaTools::Hash do
|
8
8
|
|
9
9
|
context 'from_schema' do
|
10
|
-
let(:
|
10
|
+
let(:contact){Contact.new}
|
11
11
|
before :each do
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
contact.first_name = 'Peter'
|
13
|
+
contact.last_name = 'Paul'
|
14
|
+
contact.id = 'SomeID'
|
15
15
|
end
|
16
16
|
after :each do
|
17
17
|
SchemaTools::Reader.registry_reset
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'should return hash' do
|
21
|
-
hash = SchemaTools::Hash.from_schema(
|
22
|
-
hash['
|
21
|
+
hash = SchemaTools::Hash.from_schema(contact)
|
22
|
+
hash['contact']['last_name'].should == 'Paul'
|
23
23
|
end
|
24
24
|
|
25
25
|
it 'should use custom schema path' do
|
26
26
|
custom_path = File.expand_path('../../fixtures', __FILE__)
|
27
|
-
hash = SchemaTools::Hash.from_schema(
|
28
|
-
hash['
|
27
|
+
hash = SchemaTools::Hash.from_schema(contact, path: custom_path)
|
28
|
+
hash['contact']['last_name'].should == 'Paul'
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'should use custom schema' do
|
32
|
-
hash = SchemaTools::Hash.from_schema(
|
32
|
+
hash = SchemaTools::Hash.from_schema(contact, class_name: :contact)
|
33
33
|
hash['contact']['last_name'].should == 'Paul'
|
34
34
|
end
|
35
35
|
|
36
36
|
it 'should use only give fields' do
|
37
|
-
hash = SchemaTools::Hash.from_schema(
|
38
|
-
hash['
|
39
|
-
hash['
|
40
|
-
hash['
|
41
|
-
hash['
|
37
|
+
hash = SchemaTools::Hash.from_schema(contact, fields: ['id', 'last_name'])
|
38
|
+
hash['contact'].keys.length.should == 2
|
39
|
+
hash['contact']['last_name'].should == contact.last_name
|
40
|
+
hash['contact']['id'].should == contact.id
|
41
|
+
hash['contact']['first_name'].should be_nil
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
+
context 'with nested object values' do
|
46
|
+
class Client
|
47
|
+
attr_accessor :first_name, :last_name, :addresses, :id
|
48
|
+
end
|
49
|
+
class Address
|
50
|
+
attr_accessor :city, :zip
|
51
|
+
end
|
52
|
+
|
53
|
+
let(:client){Client.new}
|
54
|
+
|
55
|
+
it 'should have empty nested array values' do
|
56
|
+
hash = SchemaTools::Hash.from_schema(client)
|
57
|
+
hash['client']['addresses'].should == []
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should have nested array values' do
|
61
|
+
a1 = Address.new
|
62
|
+
a1.city = 'Cologne'
|
63
|
+
a1.zip = 50733
|
64
|
+
client.addresses = [a1]
|
65
|
+
hash = SchemaTools::Hash.from_schema(client)
|
66
|
+
hash['client']['addresses'].should == [{"address"=>{"city"=>"Cologne", "zip"=>50733}}]
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
|
45
72
|
context 'with plain nested values' do
|
46
73
|
|
47
|
-
class Lead <
|
74
|
+
class Lead < Contact
|
48
75
|
attr_accessor :links_clicked, :conversion
|
49
76
|
end
|
50
77
|
|
@@ -52,7 +79,6 @@ describe SchemaTools::Hash do
|
|
52
79
|
attr_accessor :from, :to
|
53
80
|
end
|
54
81
|
|
55
|
-
|
56
82
|
let(:lead){Lead.new}
|
57
83
|
before :each do
|
58
84
|
lead.links_clicked = ['2012-12-12', '2012-12-15', '2012-12-16']
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
class
|
3
|
+
class TestContact
|
4
4
|
include SchemaTools::Modules::Attributes
|
5
5
|
has_schema_attrs :client
|
6
6
|
end
|
@@ -13,7 +13,7 @@ end
|
|
13
13
|
describe SchemaTools::Modules::Attributes do
|
14
14
|
|
15
15
|
context 'included' do
|
16
|
-
subject {
|
16
|
+
subject { TestContact.new }
|
17
17
|
|
18
18
|
it 'should add getter methods' do
|
19
19
|
subject.should respond_to(:last_name)
|
@@ -25,6 +25,7 @@ describe SchemaTools::Modules::Attributes do
|
|
25
25
|
|
26
26
|
it 'should not add setter for readonly properties' do
|
27
27
|
subject.should_not respond_to('id=')
|
28
|
+
subject.should_not respond_to('created_at=')
|
28
29
|
end
|
29
30
|
end
|
30
31
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json_schema_tools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-10-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json
|
@@ -128,7 +128,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
128
128
|
version: '0'
|
129
129
|
segments:
|
130
130
|
- 0
|
131
|
-
hash:
|
131
|
+
hash: 2491825896483527088
|
132
132
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
133
|
none: false
|
134
134
|
requirements:
|
@@ -137,7 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
137
137
|
version: '0'
|
138
138
|
segments:
|
139
139
|
- 0
|
140
|
-
hash:
|
140
|
+
hash: 2491825896483527088
|
141
141
|
requirements: []
|
142
142
|
rubyforge_project:
|
143
143
|
rubygems_version: 1.8.24
|