ruby_json_api_client 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +25 -0
  6. data/Rakefile +2 -0
  7. data/lib/ruby_json_api_client/adapters/ams_adapter.rb +15 -0
  8. data/lib/ruby_json_api_client/adapters/json_api_adapter.rb +15 -0
  9. data/lib/ruby_json_api_client/adapters/rest_adapter.rb +80 -0
  10. data/lib/ruby_json_api_client/base.rb +98 -0
  11. data/lib/ruby_json_api_client/collection.rb +13 -0
  12. data/lib/ruby_json_api_client/serializers/ams_serializer.rb +187 -0
  13. data/lib/ruby_json_api_client/serializers/json_api_serializer.rb +93 -0
  14. data/lib/ruby_json_api_client/store.rb +171 -0
  15. data/lib/ruby_json_api_client/version.rb +3 -0
  16. data/lib/ruby_json_api_client.rb +14 -0
  17. data/ruby_json_api_client.gemspec +34 -0
  18. data/spec/integration/ams/find_spec.rb +46 -0
  19. data/spec/integration/ams/has_many_links_spec.rb +161 -0
  20. data/spec/integration/ams/has_many_sideload_spec.rb +170 -0
  21. data/spec/integration/ams/has_one_links_spec.rb +57 -0
  22. data/spec/integration/ams/has_one_sideload_spec.rb +87 -0
  23. data/spec/integration/ams/query_spec.rb +65 -0
  24. data/spec/integration/json_api/find_spec.rb +44 -0
  25. data/spec/integration/json_api/query_spec.rb +65 -0
  26. data/spec/spec_helper.rb +7 -0
  27. data/spec/support/classes.rb +26 -0
  28. data/spec/unit/adapters/json_api_spec.rb +4 -0
  29. data/spec/unit/adapters/rest_spec.rb +109 -0
  30. data/spec/unit/base_spec.rb +60 -0
  31. data/spec/unit/collection_spec.rb +17 -0
  32. data/spec/unit/serializers/ams_spec.rb +480 -0
  33. data/spec/unit/serializers/json_api_spec.rb +114 -0
  34. data/spec/unit/store_spec.rb +243 -0
  35. metadata +262 -0
@@ -0,0 +1,480 @@
1
+ require 'spec_helper'
2
+
3
+ describe RubyJsonApiClient::AmsSerializer do
4
+ let(:serializer) { RubyJsonApiClient::AmsSerializer.new }
5
+
6
+ describe :transform do
7
+ let(:json) { "{\"testing\":true, \"firstname\":\"ryan\"}" }
8
+ subject { serializer.transform(json)["testing"] }
9
+ it { should eql(true) }
10
+ end
11
+
12
+ describe :to_json do
13
+ context "using fields" do
14
+ subject { serializer.to_json(Person.new(firstname: 'ryan')) }
15
+ it do
16
+ should eq({ person: {
17
+ firstname: 'ryan',
18
+ lastname: nil
19
+ }}.to_json)
20
+ end
21
+ end
22
+
23
+ context "using a persisted model" do
24
+ subject { serializer.to_json(Person.new(id: 1, firstname: 'ryan')) }
25
+ it do
26
+ should eq({ person: {
27
+ id: 1,
28
+ firstname: 'ryan',
29
+ lastname: nil
30
+ } }.to_json)
31
+ end
32
+ end
33
+
34
+ context "using a has one relationship" do
35
+ subject do
36
+ person = Person.new(
37
+ id: 1,
38
+ firstname: 'ryan',
39
+ lastname: nil
40
+ )
41
+
42
+ person.item = Item.new(id: 2)
43
+ serializer.to_json(person)
44
+ end
45
+
46
+ it do
47
+ should eq({ person: {
48
+ id: 1,
49
+ firstname: 'ryan',
50
+ lastname: nil,
51
+ item_id: 2
52
+ } }.to_json)
53
+ end
54
+ end
55
+ end
56
+
57
+ describe :extract_single do
58
+ context "will error when" do
59
+ subject { ->{ serializer.extract_single(Person, 1, json) } }
60
+
61
+ context "no json root key exists" do
62
+ let(:json) { "{\"firstname\":\"ryan\"}" }
63
+ it { should raise_error }
64
+ end
65
+
66
+ context "no id" do
67
+ let(:json) { "{\"person\": { \"firstname\":\"ryan\" } }" }
68
+ it { should raise_error }
69
+ end
70
+
71
+ context "the id returned is not the id we are looking for" do
72
+ let(:json) { "{\"person\": { \"id\": 2, \"firstname\":\"ryan\" } }" }
73
+ it { should raise_error }
74
+ end
75
+ end
76
+
77
+ context "when payload contains" do
78
+ subject { serializer.extract_single(Person, 1, json) }
79
+
80
+ context "string ids" do
81
+ let(:json) { "{\"person\": { \"id\": \"1\", \"firstname\":\"ryan\" } }" }
82
+ it { should be_instance_of(Person) }
83
+ end
84
+
85
+ context "attributes that are defined" do
86
+ let(:json) { "{\"person\": { \"id\": \"1\", \"firstname\":\"ryan\" } }" }
87
+ it { should be_instance_of(Person) }
88
+ it { should respond_to(:firstname) }
89
+ its(:firstname) { should eq('ryan') }
90
+ end
91
+
92
+ context "attributes that are not defined" do
93
+ let(:json) { "{\"person\": { \"id\": \"1\", \"unknown\":\"ryan\" } }" }
94
+ it { should be_instance_of(Person) }
95
+ it { should_not respond_to(:unknown) }
96
+ end
97
+ end
98
+
99
+ context "using multi worded models" do
100
+ subject { serializer.extract_single(CellPhone, 1, json) }
101
+ let(:model) { subject }
102
+
103
+
104
+ let(:json) { "{\"cell_phone\": { \"id\": 1, \"number\": \"123-456-7890\" } }" }
105
+ it { should be_instance_of(CellPhone) }
106
+ its(:number) { should eq('123-456-7890') }
107
+ end
108
+ end
109
+
110
+ describe :extract_many do
111
+ context "will error when" do
112
+ subject { ->{ serializer.extract_many(Person, json) } }
113
+
114
+ context "there is no plural key in the response" do
115
+ let(:json) { "[{ \"id\": 1, \"firstname\": \"ryan\" }]" }
116
+ it { should raise_error }
117
+ end
118
+
119
+ context "there is no array of data" do
120
+ let(:json) { "{ \"id\": 1, \"firstname\": \"ryan\" }" }
121
+ it { should raise_error }
122
+ end
123
+ end
124
+
125
+ context "when payload contains" do
126
+ subject { serializer.extract_many(Person, json) }
127
+ let(:collection) { subject }
128
+
129
+ context "multiple records" do
130
+ let(:json) do
131
+ "{ \"people\": [{ \"id\": 1, \"firstname\": \"ryan\" }, { \"id\": 2, \"firstname\": \"ryan2\" }] }"
132
+ end
133
+
134
+ it { should have(2).items }
135
+
136
+ it "should serialize one of the records" do
137
+ expect(collection.first).to respond_to(:firstname)
138
+ expect(collection.first.firstname).to eq('ryan')
139
+ end
140
+ end
141
+ end
142
+
143
+ context "using a different key name" do
144
+ let(:json) do
145
+ {
146
+ peeps: [{
147
+ id: 1,
148
+ firstname: 'ryan'
149
+ }]
150
+ }.to_json
151
+ end
152
+
153
+ let(:collection) { serializer.extract_many(Person, json, "peeps") }
154
+
155
+ subject { collection }
156
+ it { should have(1).items }
157
+
158
+ context "the person" do
159
+ subject { collection.first }
160
+ it { should be_instance_of(Person) }
161
+ it { should respond_to(:firstname) }
162
+ its(:firstname) { should eq('ryan') }
163
+ end
164
+ end
165
+ end
166
+
167
+ describe :extract_many_relationship do
168
+ let(:person) { Person.new }
169
+
170
+ it "should extact relationships using links" do
171
+ expect(serializer).to receive(:extract_many_relationship_from_links)
172
+ .with(person, :items, {}, "http://items.test")
173
+ .and_return([])
174
+
175
+ person.meta = {
176
+ links: {
177
+ 'items' => "http://items.test"
178
+ }
179
+ }
180
+
181
+ serializer.extract_many_relationship(
182
+ person,
183
+ :items,
184
+ {},
185
+ "{}"
186
+ )
187
+ end
188
+
189
+ it "should extract relationships using sideloads" do
190
+ items = "[{ \"id\": 1, \"name\": \"first\" }, { \"id\": 2, \"name\": \"second\" }]"
191
+ response = "{ \"person\": { \"item_ids\": [1] }, \"items\": #{items} }"
192
+
193
+ expect(serializer).to receive(:extract_many_relationship_from_sideload)
194
+ .with(person, :items, {}, response)
195
+ .and_return([])
196
+
197
+ person.meta = {
198
+ data: {
199
+ 'item_ids' => [1]
200
+ }
201
+ }
202
+
203
+ serializer.extract_many_relationship(
204
+ person,
205
+ :items,
206
+ {},
207
+ response
208
+ )
209
+ end
210
+
211
+ it "should not try to extract sideloads if the parent record doesnt have ids" do
212
+ result = serializer.extract_many_relationship(
213
+ person,
214
+ :items,
215
+ {},
216
+ "{ \"person\": { }, \"items\": [{\"id\": 1 }] }"
217
+ )
218
+
219
+ expect(result).to match_array([])
220
+ end
221
+
222
+ it "should give an empty collection when there is no sideload or links present" do
223
+ result = serializer.extract_many_relationship(
224
+ person,
225
+ :items,
226
+ {},
227
+ "{ \"person\": { } }"
228
+ )
229
+
230
+ expect(result).to match_array([])
231
+ end
232
+ end
233
+
234
+ describe :extract_many_relationship_from_links do
235
+ let(:person) { Person.new }
236
+ let(:store) { double("store") }
237
+
238
+ before(:each) do
239
+ serializer.store = store
240
+
241
+ expect(store).to receive(:load_collection)
242
+ .with(Item, "http://www.example.com/items")
243
+ end
244
+
245
+ it "should have the store load the collection" do
246
+ serializer.extract_many_relationship_from_links(
247
+ person,
248
+ :items,
249
+ {},
250
+ "http://www.example.com/items"
251
+ )
252
+ end
253
+
254
+ it "should have the store load the collection for the given class" do
255
+ serializer.extract_many_relationship_from_links(
256
+ person,
257
+ :oddly_named_items,
258
+ { class_name: 'Item' },
259
+ "http://www.example.com/items"
260
+ )
261
+ end
262
+ end
263
+
264
+ describe :extract_many_relationship_from_sideload do
265
+ let(:person) do
266
+ Person.new(meta: {
267
+ data: {
268
+ "item_ids" => [2]
269
+ }
270
+ })
271
+ end
272
+
273
+ let(:response) do
274
+ {
275
+ person: {
276
+ id: 1,
277
+ item_ids: [2]
278
+ },
279
+ items: [
280
+ { id: 1, name: "test" },
281
+ { id: 2, name: "test 2" }
282
+ ]
283
+ }.to_json
284
+ end
285
+
286
+ it "should use extract many to pull the data" do
287
+ expect(serializer).to receive(:extract_many)
288
+ .with(Item, response, "items")
289
+ .and_return([])
290
+
291
+ serializer.extract_many_relationship_from_sideload(
292
+ person,
293
+ :items,
294
+ {},
295
+ response
296
+ )
297
+ end
298
+
299
+ it "should pass the right class name to extract many" do
300
+ expect(serializer).to receive(:extract_many)
301
+ .with(CellPhone, response, "items")
302
+ .and_return([])
303
+
304
+ serializer.extract_many_relationship_from_sideload(
305
+ person,
306
+ :items,
307
+ { class_name: 'CellPhone' },
308
+ response
309
+ )
310
+ end
311
+
312
+ it "should filter the ids in the relationship" do
313
+ result = serializer.extract_many_relationship_from_sideload(
314
+ person,
315
+ :items,
316
+ {},
317
+ response
318
+ )
319
+
320
+ expect(result).to have(1).items
321
+ expect(result.first.id).to eq(2)
322
+ end
323
+ end
324
+
325
+ describe :extract_single_relationship do
326
+ let(:person) { Person.new }
327
+ let(:item) { Item.new }
328
+ let(:response) { "{}" } # dummy response
329
+ subject { serializer.extract_single_relationship(person, :item, {}, response) }
330
+
331
+ context "from links" do
332
+ let(:person) do
333
+ Person.new(meta: { links: {
334
+ 'item' => 'http://example.com/item/1'
335
+ }})
336
+ end
337
+
338
+ before(:each) do
339
+ expect(serializer).to receive(:extract_single_relationship_from_links)
340
+ .with(person, :item, {}, "http://example.com/item/1")
341
+ .and_return(item)
342
+ end
343
+
344
+ it { should eq(item) }
345
+ end
346
+
347
+ context "from sideload" do
348
+ let(:person) do
349
+ Person.new(meta: { data: {
350
+ 'item_id' => 1
351
+ }})
352
+ end
353
+
354
+ let(:response) do
355
+ # for sideloader
356
+ {
357
+ items: [{
358
+ id: 1,
359
+ }]
360
+ }.to_json
361
+ end
362
+
363
+ before(:each) do
364
+ expect(serializer).to receive(:extract_single_relationship_from_sideload)
365
+ .with(person, :item, {}, response)
366
+ .and_return(item)
367
+ end
368
+
369
+ it { should eq(item) }
370
+ end
371
+
372
+ context "when nothing is found" do
373
+ it { should be_nil }
374
+ end
375
+ end
376
+
377
+ describe :extract_single_relationship_from_links do
378
+ let(:store) { double("store") }
379
+ let(:person) { Person.new }
380
+ let(:item) { Item.new }
381
+
382
+ before(:each) do
383
+ serializer.store = store
384
+
385
+ expect(store).to receive(:load_single)
386
+ .with(Item, nil, "http://example.com/items/1")
387
+ .and_return(item)
388
+ end
389
+
390
+ context "with no options" do
391
+ subject do
392
+ serializer.extract_single_relationship_from_links(
393
+ person, :item, {}, "http://example.com/items/1"
394
+ )
395
+ end
396
+
397
+ it { should eq(item) }
398
+ end
399
+
400
+ context "with a different class name" do
401
+ subject do
402
+ serializer.extract_single_relationship_from_links(
403
+ person, :favorite_item, { class_name: 'Item' }, "http://example.com/items/1"
404
+ )
405
+ end
406
+
407
+ it { should eq(item) }
408
+ end
409
+ end
410
+
411
+ describe :extract_single_relationship_from_sideload do
412
+ context "with no options" do
413
+ let(:person) do
414
+ Person.new(meta: { data: {
415
+ 'item_id' => 2
416
+ }})
417
+ end
418
+
419
+ subject do
420
+ serializer.extract_single_relationship_from_sideload(
421
+ person, :item, {}, response
422
+ )
423
+ end
424
+
425
+ let(:response) do
426
+ {
427
+ person: {
428
+ id: 1,
429
+ item_id: 2
430
+ },
431
+ items: [{
432
+ id: 1,
433
+ name: 'not for person'
434
+ },{
435
+ id: 2,
436
+ name: 'persons item'
437
+ }]
438
+ }.to_json
439
+ end
440
+
441
+ it { should be_instance_of(Item) }
442
+ its(:id) { should eq(2) }
443
+ its(:name) { should eq('persons item') }
444
+ end
445
+
446
+ context "with a different class name" do
447
+ let(:person) do
448
+ Person.new(meta: { data: {
449
+ 'favorite_item_id' => 2
450
+ }})
451
+ end
452
+
453
+ subject do
454
+ serializer.extract_single_relationship_from_sideload(
455
+ person, :favorite_item, { class_name: 'Item' }, response
456
+ )
457
+ end
458
+
459
+ let(:response) do
460
+ {
461
+ person: {
462
+ id: 1,
463
+ favorite_item_id: 2
464
+ },
465
+ favorite_items: [{
466
+ id: 1,
467
+ name: 'not for person'
468
+ },{
469
+ id: 2,
470
+ name: 'persons item'
471
+ }]
472
+ }.to_json
473
+ end
474
+
475
+ it { should be_instance_of(Item) }
476
+ its(:id) { should eq(2) }
477
+ its(:name) { should eq('persons item') }
478
+ end
479
+ end
480
+ end
@@ -0,0 +1,114 @@
1
+ require 'spec_helper'
2
+
3
+ describe RubyJsonApiClient do
4
+ let(:serializer) { RubyJsonApiClient::JsonApiSerializer.new }
5
+
6
+ describe :transform do
7
+ let(:json) { "{\"testing\":true, \"firstname\":\"ryan\"}" }
8
+ subject { serializer.transform(json)["testing"] }
9
+ it { should eql(true) }
10
+ end
11
+
12
+ describe :extract_single do
13
+ context "will error when" do
14
+ subject { ->{ serializer.extract_single(Person, 1, json) } }
15
+
16
+ context "no json root key exists" do
17
+ let(:json) { "{\"firstname\":\"ryan\"}" }
18
+ it { should raise_error }
19
+ end
20
+
21
+ context "single resource is not a collection" do
22
+ let(:json) { "{ \"people\": { \"firstname\":\"ryan\" } }" }
23
+ it { should raise_error }
24
+ end
25
+
26
+ context "no id" do
27
+ let(:json) { "{\"people\": [{ \"firstname\":\"ryan\" }] }" }
28
+ it { should raise_error }
29
+ end
30
+
31
+ context "the id returned is not the id we are looking for" do
32
+ let(:json) { "{\"people\": [{ \"id\": 2, \"firstname\":\"ryan\" }] }" }
33
+ it { should raise_error }
34
+ end
35
+ end
36
+
37
+ context "when payload contains" do
38
+ subject { serializer.extract_single(Person, 1, json) }
39
+
40
+ context "string ids" do
41
+ let(:json) { "{\"people\": [{ \"id\": \"1\", \"firstname\":\"ryan\" }] }" }
42
+ it { should be_instance_of(Person) }
43
+ end
44
+
45
+ context "attributes that are defined" do
46
+ let(:json) { "{\"people\": [{ \"id\": \"1\", \"firstname\":\"ryan\" }] }" }
47
+ let(:model) { subject }
48
+
49
+ it { should be_instance_of(Person) }
50
+ it { should respond_to(:firstname) }
51
+
52
+ it "should set the right values" do
53
+ expect(model.firstname).to eq('ryan')
54
+ end
55
+ end
56
+
57
+ context "attributes that are not defined" do
58
+ let(:json) { "{\"people\": [{ \"id\": \"1\", \"unknown\":\"ryan\" }] }" }
59
+ it { should be_instance_of(Person) }
60
+ it { should_not respond_to(:unknown) }
61
+ end
62
+ end
63
+
64
+ context "using multi worded models" do
65
+ subject { serializer.extract_single(CellPhone, 1, json) }
66
+ let(:model) { subject }
67
+
68
+ class CellPhone < RubyJsonApiClient::Base
69
+ field :number
70
+ end
71
+
72
+ let(:json) { "{\"cell_phones\": [{ \"id\": 1, \"number\": \"123-456-7890\" }] }" }
73
+ it { should be_instance_of(CellPhone) }
74
+
75
+ it "should set the right number" do
76
+ expect(model.number).to eq('123-456-7890')
77
+ end
78
+ end
79
+ end
80
+
81
+ describe :extract_many do
82
+ context "will error when" do
83
+ subject { ->{ serializer.extract_many(Person, json) } }
84
+
85
+ context "there is no plural key in the response" do
86
+ let(:json) { "[{ \"id\": 1, \"firstname\": \"ryan\" }]" }
87
+ it { should raise_error }
88
+ end
89
+
90
+ context "there is no array of data" do
91
+ let(:json) { "{ \"id\": 1, \"firstname\": \"ryan\" }" }
92
+ it { should raise_error }
93
+ end
94
+ end
95
+
96
+ context "when payload contains" do
97
+ subject { serializer.extract_many(Person, json) }
98
+ let(:collection) { subject }
99
+
100
+ context "multiple records" do
101
+ let(:json) do
102
+ "{ \"people\": [{ \"id\": 1, \"firstname\": \"ryan\" }, { \"id\": 2, \"firstname\": \"ryan2\" }] }"
103
+ end
104
+
105
+ it { should have(2).items }
106
+
107
+ it "should serialize one of the records" do
108
+ expect(collection.first).to respond_to(:firstname)
109
+ expect(collection.first.firstname).to eq('ryan')
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end