lhs 21.3.1 → 23.0.1

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.
@@ -37,7 +37,7 @@ describe LHS::Record do
37
37
 
38
38
  it 'warns if linked data was simply included but is paginated' do
39
39
  expect(lambda {
40
- Customer.includes(:contracts).find(1)
40
+ Customer.includes_first_page(:contracts).find(1)
41
41
  }).to output(
42
42
  %r{\[WARNING\] You included `http://datastore/customers/1/contracts`, but this endpoint is paginated. You might want to use `includes_all` instead of `includes` \(https://github.com/local-ch/lhs#includes_all-for-paginated-endpoints\)\.}
43
43
  ).to_stderr
@@ -75,7 +75,7 @@ describe LHS::Record do
75
75
  status: 200, body: { 'href' => preceding_agb_url }.to_json, headers: {}
76
76
  )
77
77
 
78
- agb = Agb.includes(:preceding_agb).first!
78
+ agb = Agb.includes_first_page(:preceding_agb).first!
79
79
  expect(agb.pdf_url).to be == 'de'
80
80
  end
81
81
 
@@ -94,7 +94,7 @@ describe LHS::Record do
94
94
  stub_request(:get, "#{datastore}/favorites/1")
95
95
  .to_return(body: { local_entry: { href: "#{datastore}/local-entries/1" } }.to_json)
96
96
 
97
- favorite = Favorite.includes(:local_entry).find(1)
97
+ favorite = Favorite.includes_first_page(:local_entry).find(1)
98
98
  expect(favorite.local_entry).to be_kind_of LocalEntry
99
99
  expect(favorite.local_entry.name).to eq 'local.ch'
100
100
  end
@@ -40,7 +40,7 @@ describe LHS::Record do
40
40
 
41
41
  it 'uses the "references" hash for all symbols of the "including" array' do
42
42
  Customer
43
- .includes(:electronic_addresses, :contact_addresses)
43
+ .includes_first_page(:electronic_addresses, :contact_addresses)
44
44
  .references(
45
45
  electronic_addresses: referencing_options,
46
46
  contact_addresses: referencing_options
@@ -92,7 +92,7 @@ describe LHS::Record do
92
92
  .to_return(body: place_hash.to_json)
93
93
  place = Place
94
94
  .options(auth: { bearer: 'XYZ' })
95
- .includes_all(:available_assets)
95
+ .includes(:available_assets)
96
96
  .find(place_id)
97
97
  expect(place.available_assets.first).to be_a(AvailableAsset)
98
98
  end
@@ -102,7 +102,7 @@ describe LHS::Record do
102
102
  .to_return(body: place_hash.to_json)
103
103
  place = Place
104
104
  .options(auth: { bearer: 'XYZ' })
105
- .includes_all(:available_assets)
105
+ .includes(:available_assets)
106
106
  .where(id: place_id)
107
107
  expect(place.available_assets.first).to be_a(AvailableAsset)
108
108
  end
@@ -112,7 +112,7 @@ describe LHS::Record do
112
112
  .to_return(body: place_hash.to_json)
113
113
  place = Place
114
114
  .options(auth: { bearer: 'XYZ' })
115
- .includes_all(:available_assets)
115
+ .includes(:available_assets)
116
116
  .find_by(id: place_id)
117
117
  expect(place.available_assets.first).to be_a(AvailableAsset)
118
118
  end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe LHS::Record do
6
+ context 'update' do
7
+
8
+ before do
9
+ class Record < LHS::Record
10
+ endpoint 'http://datastore/records/{id}'
11
+ end
12
+ end
13
+
14
+ it 'allows to directly update a record without fetching it first' do
15
+ stub_request(:post, "http://datastore/records/123")
16
+ .with(body: { name: 'Steve' }.to_json)
17
+ .to_return(status: 200, body: {}.to_json)
18
+
19
+ Record.update(
20
+ id: '123',
21
+ name: 'Steve'
22
+ )
23
+ end
24
+
25
+ it 'does not fail during an error with update' do
26
+ stub_request(:post, "http://datastore/records/123")
27
+ .with(body: { name: 'Steve' }.to_json)
28
+ .to_return(status: 404, body: {}.to_json)
29
+
30
+ record = Record.update(
31
+ id: '123',
32
+ name: 'Steve'
33
+ )
34
+
35
+ expect(record.errors.status_code).to eq 404
36
+ end
37
+
38
+ it 'allows to directly update! a record without fetching it first' do
39
+ stub_request(:post, "http://datastore/records/123")
40
+ .with(body: { name: 'Steve' }.to_json)
41
+ .to_return(status: 200)
42
+
43
+ Record.update!(
44
+ id: '123',
45
+ name: 'Steve'
46
+ )
47
+ end
48
+
49
+ it 'raises an error when trying to update! but retrieving an error status' do
50
+ stub_request(:post, "http://datastore/records/123")
51
+ .with(body: { name: 'Steve' }.to_json)
52
+ .to_return(status: 404)
53
+
54
+ expect(-> {
55
+ Record.update!(
56
+ id: '123',
57
+ name: 'Steve'
58
+ )
59
+ }).to raise_error(LHC::NotFound)
60
+ end
61
+ end
62
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lhs
3
3
  version: !ruby/object:Gem::Version
4
- version: 21.3.1
4
+ version: 23.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - https://github.com/local-ch/lhs/graphs/contributors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-15 00:00:00.000000000 Z
11
+ date: 2020-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -44,7 +44,7 @@ dependencies:
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '10'
47
+ version: 11.2.0
48
48
  - - "<"
49
49
  - !ruby/object:Gem::Version
50
50
  version: '12'
@@ -54,7 +54,7 @@ dependencies:
54
54
  requirements:
55
55
  - - ">="
56
56
  - !ruby/object:Gem::Version
57
- version: '10'
57
+ version: 11.2.0
58
58
  - - "<"
59
59
  - !ruby/object:Gem::Version
60
60
  version: '12'
@@ -312,6 +312,7 @@ files:
312
312
  - lib/lhs/concerns/record/request.rb
313
313
  - lib/lhs/concerns/record/scope.rb
314
314
  - lib/lhs/concerns/record/tracing.rb
315
+ - lib/lhs/concerns/record/update.rb
315
316
  - lib/lhs/config.rb
316
317
  - lib/lhs/data.rb
317
318
  - lib/lhs/endpoint.rb
@@ -500,7 +501,7 @@ files:
500
501
  - spec/record/href_for_spec.rb
501
502
  - spec/record/ignore_errors_spec.rb
502
503
  - spec/record/immutable_chains_spec.rb
503
- - spec/record/includes_all_spec.rb
504
+ - spec/record/includes_first_page_spec.rb
504
505
  - spec/record/includes_spec.rb
505
506
  - spec/record/includes_warning_spec.rb
506
507
  - spec/record/item_key_spec.rb
@@ -530,6 +531,7 @@ files:
530
531
  - spec/record/to_hash_spec.rb
531
532
  - spec/record/to_json_spec.rb
532
533
  - spec/record/tracing_spec.rb
534
+ - spec/record/update_spec.rb
533
535
  - spec/record/where_chains_spec.rb
534
536
  - spec/record/where_spec.rb
535
537
  - spec/record/where_values_hash_spec.rb
@@ -727,7 +729,7 @@ test_files:
727
729
  - spec/record/href_for_spec.rb
728
730
  - spec/record/ignore_errors_spec.rb
729
731
  - spec/record/immutable_chains_spec.rb
730
- - spec/record/includes_all_spec.rb
732
+ - spec/record/includes_first_page_spec.rb
731
733
  - spec/record/includes_spec.rb
732
734
  - spec/record/includes_warning_spec.rb
733
735
  - spec/record/item_key_spec.rb
@@ -757,6 +759,7 @@ test_files:
757
759
  - spec/record/to_hash_spec.rb
758
760
  - spec/record/to_json_spec.rb
759
761
  - spec/record/tracing_spec.rb
762
+ - spec/record/update_spec.rb
760
763
  - spec/record/where_chains_spec.rb
761
764
  - spec/record/where_spec.rb
762
765
  - spec/record/where_values_hash_spec.rb
@@ -1,693 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rails_helper'
4
-
5
- describe LHS::Record do
6
- context 'includes all' do
7
- before do
8
- class Customer < LHS::Record
9
- endpoint 'http://datastore/customers/{id}'
10
- end
11
-
12
- class User < LHS::Record
13
- configuration pagination_strategy: 'link'
14
- endpoint 'http://datastore/users'
15
- end
16
- end
17
-
18
- let(:amount_of_contracts) { 33 }
19
- let(:amount_of_products) { 22 }
20
- let(:amount_of_users_1st_page) { 10 }
21
- let(:amount_of_users_2nd_page) { 3 }
22
- let(:amount_of_users) { amount_of_users_1st_page + amount_of_users_2nd_page }
23
-
24
- let!(:customer_request) do
25
- stub_request(:get, 'http://datastore/customers/1')
26
- .to_return(
27
- body: {
28
- contracts: { href: 'http://datastore/customers/1/contracts' },
29
- users: { href: 'http://datastore/users?limit=10' }
30
- }.to_json
31
- )
32
- end
33
-
34
- #
35
- # Contracts
36
- #
37
-
38
- let!(:contracts_request) do
39
- stub_request(:get, "http://datastore/customers/1/contracts?limit=100")
40
- .to_return(
41
- body: {
42
- items: 10.times.map do
43
- {
44
- products: { href: 'http://datastore/products' }
45
- }
46
- end,
47
- limit: 10,
48
- offset: 0,
49
- total: amount_of_contracts
50
- }.to_json
51
- )
52
- end
53
-
54
- def additional_contracts_request(offset, amount)
55
- stub_request(:get, "http://datastore/customers/1/contracts?limit=10&offset=#{offset}")
56
- .to_return(
57
- body: {
58
- items: amount.times.map do
59
- {
60
- products: { href: 'http://datastore/products' }
61
- }
62
- end,
63
- limit: 10,
64
- offset: offset,
65
- total: amount_of_contracts
66
- }.to_json
67
- )
68
- end
69
-
70
- let!(:contracts_request_page_2) do
71
- additional_contracts_request(10, 10)
72
- end
73
-
74
- let!(:contracts_request_page_3) do
75
- additional_contracts_request(20, 10)
76
- end
77
-
78
- let!(:contracts_request_page_4) do
79
- additional_contracts_request(30, 3)
80
- end
81
-
82
- #
83
- # Products
84
- #
85
-
86
- let!(:products_request) do
87
- stub_request(:get, "http://datastore/products?limit=100")
88
- .to_return(
89
- body: {
90
- items: 10.times.map do
91
- { name: 'LBC' }
92
- end,
93
- limit: 10,
94
- offset: 0,
95
- total: amount_of_products
96
- }.to_json
97
- )
98
- end
99
-
100
- def additional_products_request(offset, amount)
101
- stub_request(:get, "http://datastore/products?limit=10&offset=#{offset}")
102
- .to_return(
103
- body: {
104
- items: amount.times.map do
105
- { name: 'LBC' }
106
- end,
107
- limit: 10,
108
- offset: offset,
109
- total: amount_of_products
110
- }.to_json
111
- )
112
- end
113
-
114
- let!(:products_request_page_2) do
115
- additional_products_request(10, 10)
116
- end
117
-
118
- let!(:products_request_page_3) do
119
- additional_products_request(20, 2)
120
- end
121
-
122
- #
123
- # Users
124
- #
125
-
126
- let!(:users_request) do
127
- stub_request(:get, 'http://datastore/users?limit=10')
128
- .to_return(
129
- body: {
130
- items: amount_of_users_1st_page.times.map do
131
- { name: 'Hans Muster' }
132
- end,
133
- limit: 10,
134
- next: { href: 'http://datastore/users?for_user_id=10&limit=10' }
135
- }.to_json
136
- )
137
- end
138
-
139
- let!(:users_request_page_2) do
140
- stub_request(:get, 'http://datastore/users?for_user_id=10&limit=10')
141
- .to_return(
142
- body: {
143
- items: amount_of_users_2nd_page.times.map do
144
- { name: 'Lisa Müller' }
145
- end,
146
- limit: 10,
147
- next: { href: 'http://datastore/users?for_user_id=13&limit=10' }
148
- }.to_json
149
- )
150
- end
151
-
152
- let!(:users_request_page_3) do
153
- stub_request(:get, 'http://datastore/users?for_user_id=13&limit=10')
154
- .to_return(
155
- body: {
156
- items: [],
157
- limit: 10
158
- }.to_json
159
- )
160
- end
161
-
162
- it 'includes all linked business objects no matter pagination' do
163
- customer = nil
164
-
165
- expect(lambda do
166
- customer = Customer
167
- .includes_all(:users, contracts: :products)
168
- .find(1)
169
- end).to output(
170
- %r{\[WARNING\] You are loading all pages from a resource paginated with links only. As this is performed sequentially, it can result in very poor performance! \(https://github.com/local-ch/lhs#pagination-strategy-link\).}
171
- ).to_stderr
172
-
173
- expect(customer.users.length).to eq amount_of_users
174
- expect(customer.contracts.length).to eq amount_of_contracts
175
- expect(customer.contracts.first.products.length).to eq amount_of_products
176
- expect(customer_request).to have_been_requested.at_least_once
177
- expect(contracts_request).to have_been_requested.at_least_once
178
- expect(contracts_request_page_2).to have_been_requested.at_least_once
179
- expect(contracts_request_page_3).to have_been_requested.at_least_once
180
- expect(contracts_request_page_4).to have_been_requested.at_least_once
181
- expect(products_request).to have_been_requested.at_least_once
182
- expect(products_request_page_2).to have_been_requested.at_least_once
183
- expect(products_request_page_3).to have_been_requested.at_least_once
184
- expect(users_request).to have_been_requested.at_least_once
185
- expect(users_request_page_2).to have_been_requested.at_least_once
186
- expect(users_request_page_3).to have_been_requested.at_least_once
187
- end
188
-
189
- context 'links already contain pagination parameters' do
190
- let!(:customer_request) do
191
- stub_request(:get, 'http://datastore/customers/1')
192
- .to_return(
193
- body: {
194
- contracts: { href: 'http://datastore/customers/1/contracts?limit=5&offset=0' }
195
- }.to_json
196
- )
197
- end
198
-
199
- let!(:contracts_request) do
200
- stub_request(:get, "http://datastore/customers/1/contracts?limit=100")
201
- .to_return(
202
- body: {
203
- items: 10.times.map do
204
- {
205
- products: { href: 'http://datastore/products' }
206
- }
207
- end,
208
- limit: 10,
209
- offset: 0,
210
- total: amount_of_contracts
211
- }.to_json
212
- )
213
- end
214
-
215
- it 'overwrites existing pagination paramters if they are already contained in a string' do
216
- expect(LHC).to receive(:request)
217
- .with(url: "http://datastore/customers/1").and_call_original
218
-
219
- expect(LHC).to receive(:request)
220
- .with(url: "http://datastore/customers/1/contracts",
221
- all: true,
222
- params: { limit: 100 }).and_call_original
223
-
224
- expect(LHC).to receive(:request)
225
- .with([{ url: "http://datastore/customers/1/contracts",
226
- all: true,
227
- params: { limit: 10, offset: 10 } },
228
- { url: "http://datastore/customers/1/contracts",
229
- all: true,
230
- params: { limit: 10, offset: 20 } },
231
- { url: "http://datastore/customers/1/contracts",
232
- all: true,
233
- params: { limit: 10, offset: 30 } }]).and_call_original
234
-
235
- customer = Customer
236
- .includes_all(:contracts)
237
- .find(1)
238
- expect(customer.contracts.length).to eq amount_of_contracts
239
- end
240
- end
241
-
242
- context 'includes for an empty array' do
243
- before do
244
- class Contract < LHS::Record
245
- endpoint 'http://datastore/contracts/{id}'
246
- end
247
- stub_request(:get, %r{http://datastore/contracts/\d})
248
- .to_return(body: {
249
- options: nested_resources
250
- }.to_json)
251
- end
252
-
253
- context 'empty array' do
254
- let(:nested_resources) { [] }
255
-
256
- it 'includes_all in case of an empty array' do
257
- expect(
258
- -> { Contract.includes(:product).includes_all(:options).find(1) }
259
- ).not_to raise_error
260
- expect(
261
- -> { Contract.includes(:product).includes_all(:options).find(1, 2) }
262
- ).not_to raise_error
263
- end
264
- end
265
-
266
- context 'weird array without hrefs' do
267
- before do
268
- stub_request(:get, "http://datastore/options/1?limit=100")
269
- .to_return(body: { type: 'REACH_EXT' }.to_json)
270
- end
271
-
272
- let(:nested_resources) { [{ href: 'http://datastore/options/1' }, { type: 'E_COMMERCE' }] }
273
-
274
- it 'includes_all in case of an unexpect objects within array' do
275
- expect(
276
- -> { Contract.includes(:product).includes_all(:options).find(1) }
277
- ).not_to raise_error
278
- expect(
279
- -> { Contract.includes(:product).includes_all(:options).find(1, 2) }
280
- ).not_to raise_error
281
- end
282
- end
283
- end
284
-
285
- context 'include a known/identifiable record' do
286
- before do
287
- class Contract < LHS::Record
288
- endpoint 'http://datastore/contracts/{id}'
289
- end
290
-
291
- class Entry < LHS::Record
292
- endpoint '{+datastore}/entry/v1/{id}.json'
293
- end
294
-
295
- LHC.config.placeholder(:datastore, 'http://datastore')
296
- end
297
-
298
- let!(:customer_request) do
299
- stub_request(:get, %r{http://datastore/customers/\d+})
300
- .to_return(
301
- body: {
302
- contracts: [{ href: 'http://datastore/contracts/1' }, { href: 'http://datastore/contracts/2' }]
303
- }.to_json
304
- )
305
- end
306
-
307
- let!(:contracts_request) do
308
- stub_request(:get, %r{http://datastore/contracts/\d+})
309
- .to_return(
310
- body: {
311
- type: 'contract',
312
- entry: { href: 'http://datastore/entry/v1/1.json' }
313
- }.to_json
314
- )
315
- end
316
-
317
- let!(:entry_request) do
318
- stub_request(:get, %r{http://datastore/entry/v1/\d+.json})
319
- .to_return(
320
- body: {
321
- name: 'Casa Ferlin'
322
- }.to_json
323
- )
324
- end
325
-
326
- it 'loads included identifiable records without raising exceptions' do
327
- customer = Customer.includes_all(contracts: :entry).find(1, 2).first
328
- expect(customer.contracts.first.href).to eq 'http://datastore/contracts/1'
329
- expect(customer.contracts.first.type).to eq 'contract'
330
- expect(customer.contracts.first.entry.name).to eq 'Casa Ferlin'
331
- end
332
- end
333
-
334
- context 'includes all for parallel loaded ids' do
335
- before do
336
- class Place < LHS::Record
337
- endpoint 'http://datastore/places/{id}'
338
- end
339
- end
340
-
341
- let!(:place_request_1) do
342
- stub_request(:get, %r{http://datastore/places/1})
343
- .to_return(
344
- body: {
345
- category_relations: [
346
- { href: 'http://datastore/category_relations/1' },
347
- { href: 'http://datastore/category_relations/2' }
348
- ]
349
- }.to_json
350
- )
351
- end
352
-
353
- let!(:place_request_2) do
354
- stub_request(:get, %r{http://datastore/places/2})
355
- .to_return(
356
- body: {
357
- category_relations: []
358
- }.to_json
359
- )
360
- end
361
-
362
- let!(:place_request_3) do
363
- stub_request(:get, %r{http://datastore/places/3})
364
- .to_return(
365
- body: {
366
- category_relations: [
367
- { href: 'http://datastore/category_relations/1' },
368
- { href: 'http://datastore/category_relations/3' }
369
- ]
370
- }.to_json
371
- )
372
- end
373
-
374
- let!(:category_relation_request_1) do
375
- stub_request(:get, %r{http://datastore/category_relations/1})
376
- .to_return(
377
- body: {
378
- name: "Category 1"
379
- }.to_json
380
- )
381
- end
382
-
383
- let!(:category_relation_request_2) do
384
- stub_request(:get, %r{http://datastore/category_relations/2})
385
- .to_return(
386
- body: {
387
- name: "Category 2"
388
- }.to_json
389
- )
390
- end
391
-
392
- let!(:category_relation_request_3) do
393
- stub_request(:get, %r{http://datastore/category_relations/3})
394
- .to_return(
395
- body: {
396
- name: "Category 3"
397
- }.to_json
398
- )
399
- end
400
-
401
- let(:category_name) { 'Category Relation' }
402
-
403
- it 'requests places in parallel and includes category relation' do
404
- places = Place.includes_all(:category_relations).find(1, 2, 3)
405
- expect(places[0].category_relations[0].name).to eq 'Category 1'
406
- expect(places[0].category_relations[1].name).to eq 'Category 2'
407
- expect(places[2].category_relations[0].name).to eq 'Category 1'
408
- expect(places[2].category_relations[1].name).to eq 'Category 3'
409
- end
410
- end
411
- end
412
-
413
- context 'Linked resources' do
414
- before do
415
- stub_request(:get, 'http://datastore/places/1/contracts?offset=0&limit=10')
416
- .to_return(
417
- body: {
418
- href: "http://datastore/v2/places/1/contracts?offset=0&limit=10",
419
- items: [{ href: "http://datastore/v2/contracts/1" }],
420
- offset: 0,
421
- limit: 10,
422
- total: 10
423
- }.to_json
424
- )
425
-
426
- stub_request(:get, "http://datastore/v2/contracts/1")
427
- .to_return(
428
- body: {
429
- customer: { name: 'Swisscom Directories AG' }
430
- }.to_json
431
- )
432
-
433
- stub_request(:get, 'http://datastore/places/1?limit=1')
434
- .to_return(
435
- body: { href: 'http://datastore/places/1', contracts: { href: 'http://datastore/places/1/contracts?offset=0&limit=10' } }.to_json
436
- )
437
-
438
- class Place < LHS::Record
439
- endpoint 'http://datastore/places/{id}'
440
- end
441
-
442
- class Contract < LHS::Record
443
- endpoint 'http://datastore/places/{place_id}/contracts'
444
- end
445
- end
446
-
447
- it 'does not use the root record endpoints when including nested records' do
448
- place = Place
449
- .includes_all(:contracts)
450
- .find_by(id: 1)
451
- expect(place.contracts.first.customer.name).to eq 'Swisscom Directories AG'
452
- end
453
- end
454
-
455
- context 'nested includes_all' do
456
- context 'with optional children' do
457
-
458
- let(:favorites_request_stub) do
459
- stub_request(:get, %r{http://datastore/favorites})
460
- .to_return(
461
- body: {
462
- items: [{
463
- href: "http://datastore/favorites/1",
464
- place: {
465
- href: "http://datastore/places/1"
466
- }
467
- }, {
468
- href: "http://datastore/favorite/2",
469
- place: {
470
- href: "http://datastore/places/2"
471
- }
472
- }, {
473
- href: "http://datastore/favorite/3",
474
- place: {
475
- href: "http://datastore/places/3"
476
- }
477
- }],
478
- total: 3,
479
- offset: 0,
480
- limit: 100
481
- }.to_json
482
- )
483
- end
484
-
485
- let(:place1_request_stub) do
486
- stub_request(:get, %r{http://datastore/places/1})
487
- .to_return(
488
- body: {
489
- href: "http://datastore/places/1",
490
- name: 'Place 1',
491
- contracts: {
492
- href: "http://datastore/places/1/contracts"
493
- }
494
- }.to_json
495
- )
496
- end
497
-
498
- let(:place2_request_stub) do
499
- stub_request(:get, %r{http://datastore/places/2})
500
- .to_return(
501
- body: {
502
- href: "http://datastore/places/2",
503
- name: 'Place 2'
504
- }.to_json
505
- )
506
- end
507
-
508
- let(:place3_request_stub) do
509
- stub_request(:get, %r{http://datastore/places/3})
510
- .to_return(
511
- body: {
512
- href: "http://datastore/places/3",
513
- name: 'Place 3',
514
- contracts: {
515
- href: "http://datastore/places/3/contracts"
516
- }
517
- }.to_json
518
- )
519
- end
520
-
521
- let(:contracts_request_for_place1_stub) do
522
- stub_request(:get, %r{http://datastore/places/1/contracts})
523
- .to_return(
524
- body: {
525
- items: [{
526
- href: "http://datastore/places/1/contracts/1",
527
- name: 'Contract 1'
528
- }],
529
- total: 1,
530
- offset: 0,
531
- limit: 10
532
- }.to_json
533
- )
534
- end
535
-
536
- let(:contracts_request_for_place3_stub) do
537
- stub_request(:get, %r{http://datastore/places/3/contracts})
538
- .to_return(
539
- body: {
540
- items: [{
541
- href: "http://datastore/places/3/contracts/1",
542
- name: 'Contract 3'
543
- }],
544
- total: 1,
545
- offset: 0,
546
- limit: 10
547
- }.to_json
548
- )
549
- end
550
-
551
- before do
552
- class Favorite < LHS::Record
553
- endpoint 'http://datastore/favorites'
554
- end
555
-
556
- class Place < LHS::Record
557
- endpoint 'http://datastore/places/{id}'
558
- end
559
-
560
- class Contract < LHS::Record
561
- endpoint 'http://datastore/places/{place_id}/contracts'
562
- end
563
-
564
- favorites_request_stub
565
- place1_request_stub
566
- place2_request_stub
567
- place3_request_stub
568
- contracts_request_for_place1_stub
569
- contracts_request_for_place3_stub
570
- end
571
-
572
- it 'includes nested objects when they exist' do
573
- favorites = Favorite.includes(:place).includes_all(place: :contracts).all
574
-
575
- expect(favorites.first.place.name).to eq('Place 1')
576
- expect(favorites.first.place.contracts.first.name).to eq('Contract 1')
577
- end
578
-
579
- it 'does not include nested objects when they are not there' do
580
- favorites = Favorite.includes(:place).includes_all(place: :contracts).all
581
-
582
- expect(favorites[1].place.name).to eq('Place 2')
583
- expect(favorites[1].place.contracts).to be(nil)
584
- end
585
-
586
- it 'does include and merges objects after nil objects in collections' do
587
- favorites = Favorite.includes(:place).includes_all(place: :contracts).all
588
-
589
- expect(favorites.last.place.name).to eq('Place 3')
590
- expect(favorites.last.place.contracts.first.name).to eq('Contract 3')
591
- end
592
- end
593
- end
594
-
595
- context 'includes collection trough single item' do
596
-
597
- before do
598
- class Place < LHS::Record
599
- endpoint 'https://places/{id}'
600
- end
601
-
602
- stub_request(:get, 'https://places/1')
603
- .to_return(
604
- body: {
605
- customer: { href: 'https://customers/1' }
606
- }.to_json
607
- )
608
-
609
- stub_request(:get, 'https://customers/1?limit=100')
610
- .to_return(
611
- body: {
612
- addresses: { 'href': 'https://customer/1/addresses' }
613
- }.to_json
614
- )
615
-
616
- stub_request(:get, 'https://customer/1/addresses?limit=100')
617
- .to_return(
618
- body: {
619
- items: [
620
- { city: 'Zurich', no: 1 },
621
- { city: 'Zurich', no: 2 }
622
- ],
623
- total: 2
624
- }.to_json
625
- )
626
- end
627
-
628
- it 'includes a collection trough a single item without exceptions' do
629
- place = Place
630
- .includes_all(customer: :addresses)
631
- .find(1)
632
- expect(place.customer.addresses.map(&:no)).to eq [1, 2]
633
- end
634
- end
635
-
636
- context 'does not fail including all linked resources' do
637
-
638
- before do
639
- class CustomerOnboardingToken < LHS::Record
640
- endpoint 'https://token/{id}'
641
- end
642
-
643
- class Place < LHS::Record
644
- endpoint 'https://places/{id}'
645
- end
646
-
647
- class AvailableAsset < LHS::Record
648
- endpoint 'https://assets'
649
- end
650
-
651
- stub_request(:get, 'https://token/1')
652
- .to_return(
653
- body: {
654
- places: [{ href: 'https://places/1' }]
655
- }.to_json
656
- )
657
-
658
- stub_request(:get, 'https://places/1?limit=100')
659
- .to_return(
660
- body: {
661
- available_assets: { 'href': 'https://assets?limit=10&offset=0' }
662
- }.to_json
663
- )
664
-
665
- stub_request(:get, 'https://assets?limit=10&offset=0')
666
- .to_return(
667
- body: {
668
- items: 10.times.map { { asset_code: 'CATEGORIES' } },
669
- total: 17,
670
- offset: 0,
671
- limit: 10
672
- }.to_json
673
- )
674
-
675
- stub_request(:get, 'https://assets?limit=10&offset=10')
676
- .to_return(
677
- body: {
678
- items: 7.times.map { { asset_code: 'CATEGORIES' } },
679
- total: 17,
680
- offset: 0,
681
- limit: 10
682
- }.to_json
683
- )
684
- end
685
-
686
- it 'includes a collection trough a single item without exceptions' do
687
- token = CustomerOnboardingToken
688
- .includes_all(places: :available_assets)
689
- .find(1)
690
- expect(token.places.first.available_assets.length).to eq 17
691
- end
692
- end
693
- end