http-api-tools 0.1.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 +15 -0
- data/.gitignore +18 -0
- data/.rspec +3 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +485 -0
- data/Rakefile +4 -0
- data/http-api-tools.gemspec +29 -0
- data/lib/hat/base_json_serializer.rb +107 -0
- data/lib/hat/expanded_relation_includes.rb +77 -0
- data/lib/hat/identity_map.rb +42 -0
- data/lib/hat/json_serializer_dsl.rb +62 -0
- data/lib/hat/model/acts_like_active_model.rb +16 -0
- data/lib/hat/model/attributes.rb +159 -0
- data/lib/hat/model/has_many_array.rb +47 -0
- data/lib/hat/model/transformers/date_time_transformer.rb +31 -0
- data/lib/hat/model/transformers/registry.rb +55 -0
- data/lib/hat/model.rb +2 -0
- data/lib/hat/nesting/json_serializer.rb +45 -0
- data/lib/hat/nesting/relation_loader.rb +89 -0
- data/lib/hat/relation_includes.rb +140 -0
- data/lib/hat/serializer_registry.rb +27 -0
- data/lib/hat/sideloading/json_deserializer.rb +121 -0
- data/lib/hat/sideloading/json_deserializer_mapping.rb +27 -0
- data/lib/hat/sideloading/json_serializer.rb +125 -0
- data/lib/hat/sideloading/relation_sideloader.rb +79 -0
- data/lib/hat/sideloading/sideload_map.rb +54 -0
- data/lib/hat/type_key_resolver.rb +27 -0
- data/lib/hat/version.rb +3 -0
- data/lib/hat.rb +9 -0
- data/reports/empty.png +0 -0
- data/reports/minus.png +0 -0
- data/reports/plus.png +0 -0
- data/spec/hat/expanded_relation_includes_spec.rb +32 -0
- data/spec/hat/identity_map_spec.rb +31 -0
- data/spec/hat/model/attributes_spec.rb +170 -0
- data/spec/hat/model/has_many_array_spec.rb +48 -0
- data/spec/hat/model/transformers/date_time_transformer_spec.rb +36 -0
- data/spec/hat/model/transformers/registry_spec.rb +53 -0
- data/spec/hat/nesting/json_serializer_spec.rb +173 -0
- data/spec/hat/relation_includes_spec.rb +185 -0
- data/spec/hat/sideloading/json_deserializer_spec.rb +93 -0
- data/spec/hat/sideloading/json_serializer_performance_spec.rb +51 -0
- data/spec/hat/sideloading/json_serializer_spec.rb +185 -0
- data/spec/hat/sideloading/sideload_map_spec.rb +59 -0
- data/spec/hat/support/company_deserializer_mapping.rb +11 -0
- data/spec/hat/support/person_deserializer_mapping.rb +9 -0
- data/spec/hat/support/spec_models.rb +89 -0
- data/spec/hat/support/spec_nesting_serializers.rb +41 -0
- data/spec/hat/support/spec_sideloading_serializers.rb +41 -0
- data/spec/hat/type_key_resolver_spec.rb +19 -0
- data/spec/spec_helper.rb +8 -0
- metadata +214 -0
@@ -0,0 +1,93 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'hat/sideloading/json_deserializer'
|
5
|
+
require 'hat/support/company_deserializer_mapping'
|
6
|
+
require 'hat/support/person_deserializer_mapping'
|
7
|
+
|
8
|
+
module Hat
|
9
|
+
|
10
|
+
module Sideloading
|
11
|
+
|
12
|
+
describe JsonDeserializer do
|
13
|
+
|
14
|
+
let(:json) do
|
15
|
+
{
|
16
|
+
'meta' => {
|
17
|
+
'type' => 'company',
|
18
|
+
'root_key' => 'companies'
|
19
|
+
},
|
20
|
+
'companies' => [{
|
21
|
+
'id' => 1,
|
22
|
+
'name' => "Hooroo",
|
23
|
+
'brand' => "We are travellers or something",
|
24
|
+
'links' => {
|
25
|
+
'employees' => [10, 11, 12],
|
26
|
+
'address' => 20,
|
27
|
+
'suppliers' => [30],
|
28
|
+
'parent_company' => 40
|
29
|
+
}
|
30
|
+
}],
|
31
|
+
'linked' => {
|
32
|
+
'people' => [
|
33
|
+
{'id' => 10, 'first_name' => 'Rob', 'links' => { 'employer' => 1 } },
|
34
|
+
{'id' => 11, 'first_name' => 'Stu', 'links' => { 'employer' => 1 } },
|
35
|
+
{'id' => 12, 'first_name' => 'Dan', 'links' => { 'employer' => 1 } },
|
36
|
+
],
|
37
|
+
'addresses' => [
|
38
|
+
{'id' => 20, 'street_address' => "1 Burke Street"}
|
39
|
+
]
|
40
|
+
}
|
41
|
+
|
42
|
+
}
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
let(:company) do
|
47
|
+
JsonDeserializer.new(json).deserialize.first
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "basic deserialization" do
|
51
|
+
|
52
|
+
it "creates model from the root object" do
|
53
|
+
expect(company.id).to eq json['companies'][0]['id']
|
54
|
+
expect(company.name).to eq json['companies'][0]['name']
|
55
|
+
end
|
56
|
+
|
57
|
+
it "can set read-only attributes" do
|
58
|
+
expect(company.brand).to eq json['companies'][0]['brand']
|
59
|
+
end
|
60
|
+
|
61
|
+
it "includes sideloaded has many relationships" do
|
62
|
+
expect(company.employees.size).to eql 3
|
63
|
+
expect(company.employees.first.first_name).to eq json['linked']['people'].first['first_name']
|
64
|
+
end
|
65
|
+
|
66
|
+
it "includes sideloaded has_one relationships" do
|
67
|
+
expect(company.address.street_address).to eq json['linked']['addresses'].first['street_address']
|
68
|
+
end
|
69
|
+
|
70
|
+
it "includes circular relationships" do
|
71
|
+
expect(company.employees.first.employer.name).to eq json['companies'][0]['name']
|
72
|
+
end
|
73
|
+
|
74
|
+
it "has_many relationships without sideloaded data are set to an empty array" do
|
75
|
+
expect(company.suppliers).to eql []
|
76
|
+
end
|
77
|
+
|
78
|
+
it "has_many relationships without sideloaded data have relation_ids attribute set to the ids of the relationship" do
|
79
|
+
expect(company.supplier_ids).to eql [30]
|
80
|
+
end
|
81
|
+
|
82
|
+
it "has_one relationships without sideloaded data are set to nil" do
|
83
|
+
expect(company.parent_company).to eql nil
|
84
|
+
end
|
85
|
+
|
86
|
+
it "has_one relationships without sideloaded data sets the relation_id attribute set to the id" do
|
87
|
+
expect(company.parent_company_id).to eql 40
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ruby-prof'
|
3
|
+
|
4
|
+
module Hat
|
5
|
+
module Sideloading
|
6
|
+
|
7
|
+
# Rudimentary performance profiler - uncomment to run on demand for now
|
8
|
+
|
9
|
+
|
10
|
+
# describe JsonSerializer do
|
11
|
+
|
12
|
+
# let!(:companies) do
|
13
|
+
# start = Time.now
|
14
|
+
# companies = (1..100).map do |company_id|
|
15
|
+
# company = Company.new(id: company_id, name: "Company #{rand(company_id)}")
|
16
|
+
# people = (1..100).map do |person_id|
|
17
|
+
# person = Person.new(id: person_id, first_name: "First #{rand(person_id)}", last_name: "Last #{rand(person_id)}", dob: Date.today, email: 'user@example.com', employer: company)
|
18
|
+
# skills = (1..20).map do |skill_id|
|
19
|
+
# skill = Skill.new(id: skill_id, name: "Skill #{rand(skill_id)}", description: "abc123" * 500, person: person)
|
20
|
+
# end
|
21
|
+
# person.skills = skills
|
22
|
+
# person
|
23
|
+
# end
|
24
|
+
# company.employees = people
|
25
|
+
# company
|
26
|
+
# end
|
27
|
+
# puts "BUILD MODEL: #{(Time.now - start) * 1000} ms"
|
28
|
+
# companies
|
29
|
+
# end
|
30
|
+
|
31
|
+
# it "serializes" do
|
32
|
+
# RubyProf.start
|
33
|
+
# serialized = CompanySerializer.new(companies).includes(:employer, {employees: [:skills]}).as_json
|
34
|
+
# result = RubyProf.stop
|
35
|
+
# printer = RubyProf::CallStackPrinter.new(result)
|
36
|
+
# report_file = File.open(File.expand_path("../../../reports/profile_report.html", __FILE__), "w")
|
37
|
+
# printer.print(report_file)
|
38
|
+
|
39
|
+
# start = Time.now
|
40
|
+
# serialized = CompanySerializer.new(companies).includes(:employer, {employees: [:skills]}).as_json
|
41
|
+
# puts "SERIALIZE: #{(Time.now - start) * 1000} ms"
|
42
|
+
|
43
|
+
# start = Time.now
|
44
|
+
# JSON.fast_generate(serialized)
|
45
|
+
# puts "TO_JSON: #{(Time.now - start) * 1000} ms"
|
46
|
+
|
47
|
+
# end
|
48
|
+
|
49
|
+
# end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'hat/sideloading/json_serializer'
|
5
|
+
|
6
|
+
module Hat
|
7
|
+
module Sideloading
|
8
|
+
|
9
|
+
describe JsonSerializer do
|
10
|
+
|
11
|
+
let(:company) { Company.new(id: 1, name: 'Hooroo') }
|
12
|
+
let(:person) { Person.new(id: 2, first_name: 'Rob', last_name: 'Monie') }
|
13
|
+
let(:skill) { Skill.new(id: 3, name: "JSON Serialization") }
|
14
|
+
let(:skill2) { Skill.new(id: 4, name: "JSON Serialization 2") }
|
15
|
+
|
16
|
+
before do
|
17
|
+
company.employees = [person]
|
18
|
+
person.employer = company
|
19
|
+
person.skills = [skill, skill2]
|
20
|
+
skill.person = person
|
21
|
+
skill2.person = person
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "serialization of data" do
|
25
|
+
context "with a single top-level serializable object that has relationship names different to model class" do
|
26
|
+
|
27
|
+
context "without any includes" do
|
28
|
+
|
29
|
+
let(:serialized) { PersonSerializer.new(person).as_json.with_indifferent_access }
|
30
|
+
let(:serialized_person) { serialized[:people].first }
|
31
|
+
|
32
|
+
it "serializes basic attributes" do
|
33
|
+
expect(serialized_person[:id]).to eql person.id
|
34
|
+
expect(serialized_person[:first_name]).to eql person.first_name
|
35
|
+
expect(serialized_person[:last_name]).to eql person.last_name
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'expect basic attributes with no value' do
|
39
|
+
expect(serialized_person.has_key?(:dob)).to be_true
|
40
|
+
end
|
41
|
+
|
42
|
+
it "serializes attributes defined as methods on the serializer" do
|
43
|
+
expect(serialized_person[:full_name]).to eql "#{person.first_name} #{person.last_name}"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "serializes relationships as ids" do
|
47
|
+
expect(serialized_person[:links][:employer]).to eql person.employer.id
|
48
|
+
expect(serialized_person[:links][:skills]).to eql person.skills.map(&:id)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "doesn't serialize any relationships" do
|
52
|
+
expect(serialized[:linked][:companies]).to be_nil
|
53
|
+
expect(serialized[:linked][:skills]).to be_nil
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
context "with relations specified as includes" do
|
59
|
+
|
60
|
+
let(:serializer) { PersonSerializer.new(person).includes(:employer, {skills: [:person]}) }
|
61
|
+
|
62
|
+
let(:serialized) do
|
63
|
+
serializer.as_json.with_indifferent_access
|
64
|
+
end
|
65
|
+
|
66
|
+
let(:serialized_person) { serialized[:people].first }
|
67
|
+
|
68
|
+
it "serializes relationships as ids" do
|
69
|
+
expect(serialized_person[:links][:employer]).to eql person.employer.id
|
70
|
+
expect(serialized_person[:links][:skills]).to eql person.skills.map(&:id)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "sideloads has_one relationships" do
|
74
|
+
expect(serialized[:linked][:companies].first[:name]).to eql person.employer.name
|
75
|
+
end
|
76
|
+
|
77
|
+
it "sideloads has_many relationships" do
|
78
|
+
expect(serialized[:linked][:skills].first[:name]).to eql person.skills.first.name
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#includes_for_query" do
|
82
|
+
|
83
|
+
let(:includes_for_query) { serializer.includes_for_query }
|
84
|
+
|
85
|
+
it "expands includes for included relationships and has_many relationships for fetching ids" do
|
86
|
+
expect(includes_for_query.find(:employer)).to eq({ employer: [:employees] })
|
87
|
+
expect(includes_for_query.find(:skills)).to eq({ skills: [{ person: [:skills] }] })
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
context "with an array as the serializable object" do
|
97
|
+
|
98
|
+
let(:relation) do
|
99
|
+
[person, second_person]
|
100
|
+
end
|
101
|
+
|
102
|
+
let(:second_person) { Person.new(id: 5, first_name: 'Stu', last_name: 'Liston') }
|
103
|
+
let(:serialized) { JSON.parse(PersonSerializer.new(relation).to_json).with_indifferent_access }
|
104
|
+
|
105
|
+
before do
|
106
|
+
company.employees = [person, second_person]
|
107
|
+
person.employer = company
|
108
|
+
second_person.employer = company
|
109
|
+
person.skills = [skill]
|
110
|
+
second_person.skills = []
|
111
|
+
skill.person = person
|
112
|
+
end
|
113
|
+
|
114
|
+
it "serializes basic attributes of all items in the array" do
|
115
|
+
expect(serialized[:people][0][:id]).to eql person.id
|
116
|
+
expect(serialized[:people][0][:first_name]).to eql person.first_name
|
117
|
+
expect(serialized[:people][0][:last_name]).to eql person.last_name
|
118
|
+
expect(serialized[:people][0][:id]).to eql person.id
|
119
|
+
|
120
|
+
expect(serialized[:people][1][:id]).to eql second_person.id
|
121
|
+
expect(serialized[:people][1][:first_name]).to eql second_person.first_name
|
122
|
+
expect(serialized[:people][1][:last_name]).to eql second_person.last_name
|
123
|
+
expect(serialized[:people][1][:id]).to eql second_person.id
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "meta data" do
|
129
|
+
|
130
|
+
let(:serializer) { PersonSerializer.new(person) }
|
131
|
+
|
132
|
+
it "adds root key" do
|
133
|
+
expect(serializer.as_json[:meta][:root_key]).to eql 'people'
|
134
|
+
end
|
135
|
+
|
136
|
+
it "adds type" do
|
137
|
+
expect(serializer.as_json[:meta][:type]).to eql 'person'
|
138
|
+
end
|
139
|
+
|
140
|
+
it "allows meta data to be added" do
|
141
|
+
serializer.meta(offset: 0, limit: 10)
|
142
|
+
expect(serializer.as_json[:meta][:offset]).to eql 0
|
143
|
+
expect(serializer.as_json[:meta][:limit]).to eql 10
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
describe "limiting sideloadable data" do
|
149
|
+
|
150
|
+
class LimitedSideloadingPersonSerializer < PersonSerializer
|
151
|
+
includable :employer, :skills
|
152
|
+
end
|
153
|
+
|
154
|
+
let(:unlimited_serialized) { PersonSerializer.new(person).includes(:employer, {skills: [:person]}).as_json.with_indifferent_access }
|
155
|
+
|
156
|
+
let(:limited_serialized) do
|
157
|
+
LimitedSideloadingPersonSerializer.new(person).includes(:employer, {skills: [:person]}).as_json.with_indifferent_access
|
158
|
+
end
|
159
|
+
|
160
|
+
it "does not limit sideloading if not limited in serializer" do
|
161
|
+
expect(unlimited_serialized[:linked][:people].first[:id]).to eq person.id
|
162
|
+
end
|
163
|
+
|
164
|
+
it "allows sideloading of includable relations" do
|
165
|
+
expect(limited_serialized[:linked][:skills].first[:name]).to eql person.skills.first.name
|
166
|
+
end
|
167
|
+
|
168
|
+
it "prevents sideloading of non-includable relations" do
|
169
|
+
expect(limited_serialized[:linked][:people]).to be_nil
|
170
|
+
end
|
171
|
+
|
172
|
+
it "includes what is includables in meta" do
|
173
|
+
expect(limited_serialized[:meta][:includable]).to eq 'employer,skills'
|
174
|
+
end
|
175
|
+
|
176
|
+
it "includes what was included in meta" do
|
177
|
+
expect(limited_serialized[:meta][:included]).to eq 'employer,skills'
|
178
|
+
expect(unlimited_serialized[:meta][:included]).to eq 'employer,skills,skills.person'
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'hat/sideloading/sideload_map'
|
3
|
+
|
4
|
+
module Hat
|
5
|
+
module Sideloading
|
6
|
+
|
7
|
+
describe SideloadMap do
|
8
|
+
|
9
|
+
let(:json) do
|
10
|
+
{
|
11
|
+
'meta' => {
|
12
|
+
'root_key' => 'posts'
|
13
|
+
},
|
14
|
+
'posts' => [{
|
15
|
+
'id' => 1,
|
16
|
+
'title' => 'Post Title'
|
17
|
+
}],
|
18
|
+
'linked' => {
|
19
|
+
'images' => [
|
20
|
+
{'id' => 10, 'url' => '1.png' },
|
21
|
+
{'id' => 11, 'url' => '2.png' }
|
22
|
+
],
|
23
|
+
'comments' => [
|
24
|
+
{'id' => 20, 'text' => 'Comment 1'}
|
25
|
+
]
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
let(:sideload_map) { SideloadMap.new(json, 'posts') }
|
32
|
+
|
33
|
+
describe 'getting sideloaded json from the map' do
|
34
|
+
|
35
|
+
it 'returns object at root key' do
|
36
|
+
expect(sideload_map.get('post', 1)['id']).to eql 1
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'retrieves by singular type' do
|
40
|
+
expect(sideload_map.get('image', 10)['id']).to eql 10
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'retrieves by plural type' do
|
44
|
+
expect(sideload_map.get('images', 11)['id']).to eql 11
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'retrieves with string type' do
|
48
|
+
expect(sideload_map.get('comment', 20)['id']).to eql 20
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'returns nil if object not present' do
|
52
|
+
expect(sideload_map.get('foo', 100)).to be_nil
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'hat/model'
|
4
|
+
require 'ostruct'
|
5
|
+
|
6
|
+
|
7
|
+
class Person
|
8
|
+
|
9
|
+
include Hat::Model::Attributes
|
10
|
+
|
11
|
+
attribute :id
|
12
|
+
attribute :first_name
|
13
|
+
attribute :last_name
|
14
|
+
attribute :dob
|
15
|
+
attribute :email
|
16
|
+
belongs_to :employer
|
17
|
+
has_many :skills
|
18
|
+
|
19
|
+
def employer_id
|
20
|
+
employer.try(:id)
|
21
|
+
end
|
22
|
+
|
23
|
+
#Act like active record for reflectively interogating type info
|
24
|
+
def self.reflections
|
25
|
+
{
|
26
|
+
employer: OpenStruct.new(class_name: 'Company'),
|
27
|
+
skills: OpenStruct.new(class_name: 'Skill')
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
class Company
|
34
|
+
|
35
|
+
include Hat::Model::Attributes
|
36
|
+
|
37
|
+
attribute :id
|
38
|
+
attribute :name
|
39
|
+
attribute :brand, read_only: true
|
40
|
+
has_many :employees
|
41
|
+
has_many :suppliers
|
42
|
+
belongs_to :parent_company
|
43
|
+
belongs_to :address
|
44
|
+
|
45
|
+
|
46
|
+
#Act like active record for reflectively interogating type info
|
47
|
+
def self.reflections
|
48
|
+
{
|
49
|
+
employees: OpenStruct.new(class_name: 'Person'),
|
50
|
+
suppliers: OpenStruct.new(class_name: 'Company'),
|
51
|
+
parent_company: OpenStruct.new(class_name: 'Company'),
|
52
|
+
address: OpenStruct.new(class_name: 'Address')
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
class Skill
|
59
|
+
|
60
|
+
include Hat::Model::Attributes
|
61
|
+
|
62
|
+
attribute :id
|
63
|
+
attribute :name
|
64
|
+
attribute :description
|
65
|
+
belongs_to :person
|
66
|
+
|
67
|
+
def person_id
|
68
|
+
person.try(:id)
|
69
|
+
end
|
70
|
+
|
71
|
+
#Act like active record for reflectively interogating type info
|
72
|
+
def self.reflections
|
73
|
+
{
|
74
|
+
person: OpenStruct.new(class_name: 'Person')
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
class Address
|
81
|
+
|
82
|
+
attr_accessor :id, :street_address
|
83
|
+
|
84
|
+
def initialize(attrs)
|
85
|
+
@id = attrs[:id]
|
86
|
+
@street_address = attrs[:street_address]
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'hat/nesting/json_serializer'
|
2
|
+
|
3
|
+
module Hat
|
4
|
+
module Nesting
|
5
|
+
class PersonSerializer
|
6
|
+
|
7
|
+
include Hat::Nesting::JsonSerializer
|
8
|
+
|
9
|
+
serializes Person
|
10
|
+
attributes :id, :first_name, :last_name, :full_name, :dob, :email
|
11
|
+
has_one :employer
|
12
|
+
has_many :skills
|
13
|
+
|
14
|
+
def full_name
|
15
|
+
"#{serializable.first_name} #{serializable.last_name}"
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
class CompanySerializer
|
21
|
+
|
22
|
+
include Hat::Nesting::JsonSerializer
|
23
|
+
|
24
|
+
serializes Company
|
25
|
+
attributes :id, :name
|
26
|
+
has_many :employees
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
class SkillSerializer
|
32
|
+
|
33
|
+
include Hat::Nesting::JsonSerializer
|
34
|
+
|
35
|
+
serializes Skill
|
36
|
+
attributes :id, :name, :description
|
37
|
+
has_one :person
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'hat/sideloading/json_serializer'
|
2
|
+
|
3
|
+
module Hat
|
4
|
+
module Sideloading
|
5
|
+
class PersonSerializer
|
6
|
+
|
7
|
+
include Hat::Sideloading::JsonSerializer
|
8
|
+
|
9
|
+
serializes Person
|
10
|
+
attributes :id, :first_name, :last_name, :full_name, :dob, :email
|
11
|
+
has_one :employer
|
12
|
+
has_many :skills
|
13
|
+
|
14
|
+
def full_name
|
15
|
+
"#{serializable.first_name} #{serializable.last_name}"
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
class CompanySerializer
|
21
|
+
|
22
|
+
include Hat::Sideloading::JsonSerializer
|
23
|
+
|
24
|
+
serializes Company
|
25
|
+
attributes :id, :name
|
26
|
+
has_many :employees
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
class SkillSerializer
|
32
|
+
|
33
|
+
include Hat::Sideloading::JsonSerializer
|
34
|
+
|
35
|
+
serializes Skill
|
36
|
+
attributes :id, :name, :description
|
37
|
+
has_one :person
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'hat/type_key_resolver'
|
3
|
+
|
4
|
+
module Hat
|
5
|
+
|
6
|
+
describe TypeKeyResolver do
|
7
|
+
|
8
|
+
let(:resolver) { TypeKeyResolver.new }
|
9
|
+
|
10
|
+
describe 'resolving class names' do
|
11
|
+
|
12
|
+
it 'correctly resolves the type key multiple times' do
|
13
|
+
expect(resolver.for_class(String)).to eq 'strings'
|
14
|
+
expect(resolver.for_class(String)).to eq 'strings'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
data/spec/spec_helper.rb
ADDED