lhs 21.3.0 → 23.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 +72 -11
- data/lhs.gemspec +1 -1
- data/lib/lhs/concerns/record/chainable.rb +4 -4
- data/lib/lhs/concerns/record/request.rb +19 -25
- data/lib/lhs/concerns/record/update.rb +17 -0
- data/lib/lhs/record.rb +6 -3
- data/lib/lhs/version.rb +1 -1
- data/spec/auto_oauth_spec.rb +40 -0
- data/spec/dummy/app/controllers/automatic_authentication_controller.rb +7 -0
- data/spec/dummy/app/models/dummy_record_with_auto_oauth_provider.rb +6 -0
- data/spec/dummy/app/models/providers/internal_services.rb +7 -0
- data/spec/dummy/config/routes.rb +1 -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/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 +737 -0
- data/spec/record/includes_spec.rb +545 -579
- 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/record/update_spec.rb +62 -0
- metadata +13 -6
- 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
|
@@ -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:
|
4
|
+
version: 23.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-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:
|
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:
|
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
|
@@ -388,12 +389,14 @@ files:
|
|
388
389
|
- spec/dummy/app/models/concerns/.keep
|
389
390
|
- spec/dummy/app/models/dummy_customer.rb
|
390
391
|
- spec/dummy/app/models/dummy_record.rb
|
392
|
+
- spec/dummy/app/models/dummy_record_with_auto_oauth_provider.rb
|
391
393
|
- spec/dummy/app/models/dummy_record_with_multiple_oauth_providers1.rb
|
392
394
|
- spec/dummy/app/models/dummy_record_with_multiple_oauth_providers2.rb
|
393
395
|
- spec/dummy/app/models/dummy_record_with_multiple_providers_per_endpoint.rb
|
394
396
|
- spec/dummy/app/models/dummy_record_with_oauth.rb
|
395
397
|
- spec/dummy/app/models/dummy_user.rb
|
396
398
|
- spec/dummy/app/models/providers/customer_system.rb
|
399
|
+
- spec/dummy/app/models/providers/internal_services.rb
|
397
400
|
- spec/dummy/app/views/error_handling_with_chains/error.html.erb
|
398
401
|
- spec/dummy/app/views/error_handling_with_chains/show.html.erb
|
399
402
|
- spec/dummy/app/views/form_for.html.erb
|
@@ -498,7 +501,7 @@ files:
|
|
498
501
|
- spec/record/href_for_spec.rb
|
499
502
|
- spec/record/ignore_errors_spec.rb
|
500
503
|
- spec/record/immutable_chains_spec.rb
|
501
|
-
- spec/record/
|
504
|
+
- spec/record/includes_first_page_spec.rb
|
502
505
|
- spec/record/includes_spec.rb
|
503
506
|
- spec/record/includes_warning_spec.rb
|
504
507
|
- spec/record/item_key_spec.rb
|
@@ -528,6 +531,7 @@ files:
|
|
528
531
|
- spec/record/to_hash_spec.rb
|
529
532
|
- spec/record/to_json_spec.rb
|
530
533
|
- spec/record/tracing_spec.rb
|
534
|
+
- spec/record/update_spec.rb
|
531
535
|
- spec/record/where_chains_spec.rb
|
532
536
|
- spec/record/where_spec.rb
|
533
537
|
- spec/record/where_values_hash_spec.rb
|
@@ -613,12 +617,14 @@ test_files:
|
|
613
617
|
- spec/dummy/app/models/concerns/.keep
|
614
618
|
- spec/dummy/app/models/dummy_customer.rb
|
615
619
|
- spec/dummy/app/models/dummy_record.rb
|
620
|
+
- spec/dummy/app/models/dummy_record_with_auto_oauth_provider.rb
|
616
621
|
- spec/dummy/app/models/dummy_record_with_multiple_oauth_providers1.rb
|
617
622
|
- spec/dummy/app/models/dummy_record_with_multiple_oauth_providers2.rb
|
618
623
|
- spec/dummy/app/models/dummy_record_with_multiple_providers_per_endpoint.rb
|
619
624
|
- spec/dummy/app/models/dummy_record_with_oauth.rb
|
620
625
|
- spec/dummy/app/models/dummy_user.rb
|
621
626
|
- spec/dummy/app/models/providers/customer_system.rb
|
627
|
+
- spec/dummy/app/models/providers/internal_services.rb
|
622
628
|
- spec/dummy/app/views/error_handling_with_chains/error.html.erb
|
623
629
|
- spec/dummy/app/views/error_handling_with_chains/show.html.erb
|
624
630
|
- spec/dummy/app/views/form_for.html.erb
|
@@ -723,7 +729,7 @@ test_files:
|
|
723
729
|
- spec/record/href_for_spec.rb
|
724
730
|
- spec/record/ignore_errors_spec.rb
|
725
731
|
- spec/record/immutable_chains_spec.rb
|
726
|
-
- spec/record/
|
732
|
+
- spec/record/includes_first_page_spec.rb
|
727
733
|
- spec/record/includes_spec.rb
|
728
734
|
- spec/record/includes_warning_spec.rb
|
729
735
|
- spec/record/item_key_spec.rb
|
@@ -753,6 +759,7 @@ test_files:
|
|
753
759
|
- spec/record/to_hash_spec.rb
|
754
760
|
- spec/record/to_json_spec.rb
|
755
761
|
- spec/record/tracing_spec.rb
|
762
|
+
- spec/record/update_spec.rb
|
756
763
|
- spec/record/where_chains_spec.rb
|
757
764
|
- spec/record/where_spec.rb
|
758
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
|