lhs 21.2.3 → 22.0.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 +4 -4
- data/README.md +249 -116
- data/lhs.gemspec +1 -1
- data/lib/lhs.rb +8 -0
- data/lib/lhs/concerns/o_auth.rb +25 -0
- data/lib/lhs/concerns/record/chainable.rb +4 -4
- data/lib/lhs/concerns/record/configuration.rb +28 -11
- data/lib/lhs/concerns/record/request.rb +29 -8
- data/lib/lhs/config.rb +1 -1
- data/lib/lhs/interceptors/auto_oauth/interceptor.rb +33 -0
- data/lib/lhs/interceptors/auto_oauth/thread_registry.rb +18 -0
- data/lib/lhs/version.rb +1 -1
- data/spec/auto_oauth_spec.rb +169 -0
- data/spec/dummy/app/controllers/application_controller.rb +15 -0
- data/spec/dummy/app/controllers/automatic_authentication_controller.rb +29 -0
- data/spec/dummy/app/models/dummy_record_with_auto_oauth_provider.rb +6 -0
- data/spec/dummy/app/models/dummy_record_with_multiple_oauth_providers1.rb +7 -0
- data/spec/dummy/app/models/dummy_record_with_multiple_oauth_providers2.rb +7 -0
- data/spec/dummy/app/models/dummy_record_with_multiple_providers_per_endpoint.rb +6 -0
- data/spec/dummy/app/models/dummy_record_with_oauth.rb +7 -0
- data/spec/dummy/app/models/providers/internal_services.rb +7 -0
- data/spec/dummy/config/routes.rb +5 -0
- data/spec/item/destroy_spec.rb +1 -1
- data/spec/proxy/record_identification_spec.rb +1 -1
- data/spec/record/all_spec.rb +1 -1
- data/spec/record/endpoints_spec.rb +1 -1
- data/spec/record/error_handling_integration_spec.rb +1 -1
- data/spec/record/handle_includes_errors_spec.rb +1 -1
- data/spec/record/has_many_spec.rb +1 -1
- data/spec/record/has_one_spec.rb +1 -1
- data/spec/record/includes_first_page_spec.rb +727 -0
- data/spec/record/includes_spec.rb +546 -561
- data/spec/record/includes_warning_spec.rb +1 -1
- data/spec/record/mapping_spec.rb +2 -2
- data/spec/record/references_spec.rb +1 -1
- data/spec/record/relation_caching_spec.rb +3 -3
- data/spec/request_cycle_cache_spec.rb +3 -3
- metadata +27 -8
- data/spec/record/includes_all_spec.rb +0 -693
@@ -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.
|
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
|
data/spec/record/mapping_spec.rb
CHANGED
@@ -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.
|
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.
|
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
|
-
.
|
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
|
-
.
|
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
|
-
.
|
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
|
-
.
|
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
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'rails_helper'
|
4
|
-
require 'lhc/
|
4
|
+
require 'lhc/rspec'
|
5
5
|
|
6
6
|
describe 'Request Cycle Cache', type: :request do
|
7
7
|
let!(:request) do
|
@@ -37,7 +37,7 @@ describe 'Request Cycle Cache', type: :request do
|
|
37
37
|
expect(lambda do
|
38
38
|
get '/request_cycle_cache/no_caching_interceptor'
|
39
39
|
end).to output(
|
40
|
-
%r{\[WARNING\] Can't enable request cycle cache as LHC::Caching interceptor is not enabled/configured \(see https://github.com/local-ch/lhc/blob/master/
|
40
|
+
%r{\[WARNING\] Can't enable request cycle cache as LHC::Caching interceptor is not enabled/configured \(see https://github.com/local-ch/lhc/blob/master/README.md#caching-interceptor\)!}
|
41
41
|
).to_stderr
|
42
42
|
expect(request).to have_been_made.times(2)
|
43
43
|
end
|
@@ -70,7 +70,7 @@ describe 'Request Cycle Cache', type: :request do
|
|
70
70
|
expect(lambda do
|
71
71
|
get '/request_cycle_cache/no_caching_interceptor'
|
72
72
|
end).not_to output(
|
73
|
-
%r{\[WARNING\] Can't enable request cycle cache as LHC::Caching interceptor is not enabled/configured \(see https://github.com/local-ch/lhc/blob/master/
|
73
|
+
%r{\[WARNING\] Can't enable request cycle cache as LHC::Caching interceptor is not enabled/configured \(see https://github.com/local-ch/lhc/blob/master/README.md#caching-interceptor\)!}
|
74
74
|
).to_stderr
|
75
75
|
expect(request).to have_been_made.times(2)
|
76
76
|
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:
|
4
|
+
version: 22.0.0
|
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-
|
11
|
+
date: 2020-06-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -146,16 +146,16 @@ dependencies:
|
|
146
146
|
name: rollbar
|
147
147
|
requirement: !ruby/object:Gem::Requirement
|
148
148
|
requirements:
|
149
|
-
- - "
|
149
|
+
- - "<="
|
150
150
|
- !ruby/object:Gem::Version
|
151
|
-
version:
|
151
|
+
version: 2.24.0
|
152
152
|
type: :development
|
153
153
|
prerelease: false
|
154
154
|
version_requirements: !ruby/object:Gem::Requirement
|
155
155
|
requirements:
|
156
|
-
- - "
|
156
|
+
- - "<="
|
157
157
|
- !ruby/object:Gem::Version
|
158
|
-
version:
|
158
|
+
version: 2.24.0
|
159
159
|
- !ruby/object:Gem::Dependency
|
160
160
|
name: rspec-rails
|
161
161
|
requirement: !ruby/object:Gem::Requirement
|
@@ -283,6 +283,7 @@ files:
|
|
283
283
|
- lib/lhs/concerns/item/save.rb
|
284
284
|
- lib/lhs/concerns/item/update.rb
|
285
285
|
- lib/lhs/concerns/item/validation.rb
|
286
|
+
- lib/lhs/concerns/o_auth.rb
|
286
287
|
- lib/lhs/concerns/option_blocks.rb
|
287
288
|
- lib/lhs/concerns/proxy/accessors.rb
|
288
289
|
- lib/lhs/concerns/proxy/create.rb
|
@@ -314,6 +315,8 @@ files:
|
|
314
315
|
- lib/lhs/config.rb
|
315
316
|
- lib/lhs/data.rb
|
316
317
|
- lib/lhs/endpoint.rb
|
318
|
+
- lib/lhs/interceptors/auto_oauth/interceptor.rb
|
319
|
+
- lib/lhs/interceptors/auto_oauth/thread_registry.rb
|
317
320
|
- lib/lhs/interceptors/extended_rollbar/handler.rb
|
318
321
|
- lib/lhs/interceptors/extended_rollbar/interceptor.rb
|
319
322
|
- lib/lhs/interceptors/extended_rollbar/thread_registry.rb
|
@@ -340,6 +343,7 @@ files:
|
|
340
343
|
- lib/lhs/version.rb
|
341
344
|
- script/ci/build.sh
|
342
345
|
- spec/.DS_Store
|
346
|
+
- spec/auto_oauth_spec.rb
|
343
347
|
- spec/autoloading_spec.rb
|
344
348
|
- spec/collection/accessors_spec.rb
|
345
349
|
- spec/collection/collection_items_spec.rb
|
@@ -372,6 +376,7 @@ files:
|
|
372
376
|
- spec/dummy/app/assets/javascripts/application.js
|
373
377
|
- spec/dummy/app/assets/stylesheets/application.css
|
374
378
|
- spec/dummy/app/controllers/application_controller.rb
|
379
|
+
- spec/dummy/app/controllers/automatic_authentication_controller.rb
|
375
380
|
- spec/dummy/app/controllers/concerns/.keep
|
376
381
|
- spec/dummy/app/controllers/error_handling_with_chains_controller.rb
|
377
382
|
- spec/dummy/app/controllers/extended_rollbar_controller.rb
|
@@ -383,8 +388,14 @@ files:
|
|
383
388
|
- spec/dummy/app/models/concerns/.keep
|
384
389
|
- spec/dummy/app/models/dummy_customer.rb
|
385
390
|
- spec/dummy/app/models/dummy_record.rb
|
391
|
+
- spec/dummy/app/models/dummy_record_with_auto_oauth_provider.rb
|
392
|
+
- spec/dummy/app/models/dummy_record_with_multiple_oauth_providers1.rb
|
393
|
+
- spec/dummy/app/models/dummy_record_with_multiple_oauth_providers2.rb
|
394
|
+
- spec/dummy/app/models/dummy_record_with_multiple_providers_per_endpoint.rb
|
395
|
+
- spec/dummy/app/models/dummy_record_with_oauth.rb
|
386
396
|
- spec/dummy/app/models/dummy_user.rb
|
387
397
|
- spec/dummy/app/models/providers/customer_system.rb
|
398
|
+
- spec/dummy/app/models/providers/internal_services.rb
|
388
399
|
- spec/dummy/app/views/error_handling_with_chains/error.html.erb
|
389
400
|
- spec/dummy/app/views/error_handling_with_chains/show.html.erb
|
390
401
|
- spec/dummy/app/views/form_for.html.erb
|
@@ -489,7 +500,7 @@ files:
|
|
489
500
|
- spec/record/href_for_spec.rb
|
490
501
|
- spec/record/ignore_errors_spec.rb
|
491
502
|
- spec/record/immutable_chains_spec.rb
|
492
|
-
- spec/record/
|
503
|
+
- spec/record/includes_first_page_spec.rb
|
493
504
|
- spec/record/includes_spec.rb
|
494
505
|
- spec/record/includes_warning_spec.rb
|
495
506
|
- spec/record/item_key_spec.rb
|
@@ -559,6 +570,7 @@ specification_version: 4
|
|
559
570
|
summary: 'REST services accelerator: Rails gem providing an easy, active-record-like
|
560
571
|
interface for http (hypermedia) json services'
|
561
572
|
test_files:
|
573
|
+
- spec/auto_oauth_spec.rb
|
562
574
|
- spec/autoloading_spec.rb
|
563
575
|
- spec/collection/accessors_spec.rb
|
564
576
|
- spec/collection/collection_items_spec.rb
|
@@ -591,6 +603,7 @@ test_files:
|
|
591
603
|
- spec/dummy/app/assets/javascripts/application.js
|
592
604
|
- spec/dummy/app/assets/stylesheets/application.css
|
593
605
|
- spec/dummy/app/controllers/application_controller.rb
|
606
|
+
- spec/dummy/app/controllers/automatic_authentication_controller.rb
|
594
607
|
- spec/dummy/app/controllers/concerns/.keep
|
595
608
|
- spec/dummy/app/controllers/error_handling_with_chains_controller.rb
|
596
609
|
- spec/dummy/app/controllers/extended_rollbar_controller.rb
|
@@ -602,8 +615,14 @@ test_files:
|
|
602
615
|
- spec/dummy/app/models/concerns/.keep
|
603
616
|
- spec/dummy/app/models/dummy_customer.rb
|
604
617
|
- spec/dummy/app/models/dummy_record.rb
|
618
|
+
- spec/dummy/app/models/dummy_record_with_auto_oauth_provider.rb
|
619
|
+
- spec/dummy/app/models/dummy_record_with_multiple_oauth_providers1.rb
|
620
|
+
- spec/dummy/app/models/dummy_record_with_multiple_oauth_providers2.rb
|
621
|
+
- spec/dummy/app/models/dummy_record_with_multiple_providers_per_endpoint.rb
|
622
|
+
- spec/dummy/app/models/dummy_record_with_oauth.rb
|
605
623
|
- spec/dummy/app/models/dummy_user.rb
|
606
624
|
- spec/dummy/app/models/providers/customer_system.rb
|
625
|
+
- spec/dummy/app/models/providers/internal_services.rb
|
607
626
|
- spec/dummy/app/views/error_handling_with_chains/error.html.erb
|
608
627
|
- spec/dummy/app/views/error_handling_with_chains/show.html.erb
|
609
628
|
- spec/dummy/app/views/form_for.html.erb
|
@@ -708,7 +727,7 @@ test_files:
|
|
708
727
|
- spec/record/href_for_spec.rb
|
709
728
|
- spec/record/ignore_errors_spec.rb
|
710
729
|
- spec/record/immutable_chains_spec.rb
|
711
|
-
- spec/record/
|
730
|
+
- spec/record/includes_first_page_spec.rb
|
712
731
|
- spec/record/includes_spec.rb
|
713
732
|
- spec/record/includes_warning_spec.rb
|
714
733
|
- spec/record/item_key_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
|