lhs 5.2.0 → 5.3.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 +1 -1
- data/lib/lhs/concerns/record/request.rb +39 -13
- data/lib/lhs/data.rb +1 -1
- data/lib/lhs/record.rb +1 -3
- data/lib/lhs/version.rb +1 -1
- data/spec/record/includes_spec.rb +53 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b5e2d8c23fc37ece5d7b13aebd02f43df60aec96
|
4
|
+
data.tar.gz: 650560241439a1cb5b97c86894ef4a5e133d5bd4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d086164639d3fd4b3a40a772c2c98360cf212f6b58e6d55a5debe7317daecb341e42aec62948783e79f3eb18f398a607a9cffc99a7828d73f9fc02c894cc36a
|
7
|
+
data.tar.gz: 329fbdb7a8edc677a156588061af8e99e9a15db6bec9684f50e057157f6c4489fd1eb71d5c58c8378bb7e194682b2679e77b58c0ada1f3fc2b012bdfc70c2e9d
|
data/README.md
CHANGED
@@ -293,7 +293,7 @@ feedback.ratings # {:quality=>3}
|
|
293
293
|
|
294
294
|
## Include linked resources
|
295
295
|
|
296
|
-
When fetching records, you can specify in advance all the linked resources that you want to include in the results. With `includes`, LHS ensures that all matching and explicitly linked resources are loaded and merged.
|
296
|
+
When fetching records, you can specify in advance all the linked resources that you want to include in the results. With `includes`, LHS ensures that all matching and explicitly linked resources are loaded and merged, if they're included in the server response.
|
297
297
|
|
298
298
|
The implementation is heavily influenced by [http://guides.rubyonrails.org/active_record_class_querying](http://guides.rubyonrails.org/active_record_class_querying.html#eager-loading-associations) and you should read it to understand this feature in all its glory.
|
299
299
|
|
@@ -26,6 +26,7 @@ class LHS::Record
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def convert_option_to_endpoints(option)
|
29
|
+
return unless option.present?
|
29
30
|
new_options = option.dup
|
30
31
|
url = option[:url]
|
31
32
|
endpoint = LHS::Endpoint.for_url(url)
|
@@ -38,10 +39,12 @@ class LHS::Record
|
|
38
39
|
|
39
40
|
# Extends existing raw data with additionaly fetched data
|
40
41
|
def extend_raw_data(data, addition, key)
|
41
|
-
if
|
42
|
+
return if addition.empty?
|
43
|
+
if data.collection?
|
42
44
|
data.each_with_index do |item, i|
|
43
45
|
item = item[i] if item.is_a? LHS::Collection
|
44
|
-
item
|
46
|
+
link = item[key.to_sym]
|
47
|
+
link.merge_raw!(addition[i]) if link.present?
|
45
48
|
end
|
46
49
|
elsif data._proxy.is_a? LHS::Item
|
47
50
|
data._raw[key.to_sym].merge!(addition._raw)
|
@@ -59,19 +62,25 @@ class LHS::Record
|
|
59
62
|
end
|
60
63
|
|
61
64
|
def handle_include(included, data, sub_includes = nil)
|
62
|
-
return
|
65
|
+
return if data.blank? || skip_loading_includes?(data, included)
|
63
66
|
options =
|
64
|
-
if data.
|
65
|
-
options_for_multiple(data, included)
|
67
|
+
if data.collection?
|
66
68
|
options_for_multiple(data, included)
|
67
69
|
else
|
68
70
|
url_option_for(data, included)
|
69
|
-
url_option_for(data, included)
|
70
71
|
end
|
71
72
|
addition = load_include(options, data, sub_includes)
|
72
73
|
extend_raw_data(data, addition, included)
|
73
74
|
end
|
74
75
|
|
76
|
+
def skip_loading_includes?(data, included)
|
77
|
+
if data.collection?
|
78
|
+
data.to_a.none? { |item| item[included].present? }
|
79
|
+
else
|
80
|
+
!data._raw.key?(included)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
75
84
|
# Load additional resources that are requested with include
|
76
85
|
def load_include(options, data, sub_includes)
|
77
86
|
record = record_for_options(options) || self
|
@@ -92,14 +101,31 @@ class LHS::Record
|
|
92
101
|
end
|
93
102
|
|
94
103
|
def multiple_requests(options)
|
95
|
-
options = options.map
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
104
|
+
options = options.map do |option|
|
105
|
+
next unless option.present?
|
106
|
+
process_options(option, find_endpoint(option[:params]))
|
107
|
+
end
|
108
|
+
data = LHC.request(options.compact).map { |response| LHS::Data.new(response.body, nil, self, response.request) }
|
109
|
+
data = restore_with_nils(data, locate_nils(options)) # nil objects in data provide location information for mapping
|
110
|
+
unless data.empty?
|
111
|
+
data = LHS::Data.new(data, nil, self)
|
112
|
+
handle_includes(including, data) if including
|
113
|
+
end
|
100
114
|
data
|
101
115
|
end
|
102
116
|
|
117
|
+
def locate_nils(array)
|
118
|
+
nils = []
|
119
|
+
array.each_with_index { |value, index| nils << index if value.nil? }
|
120
|
+
nils
|
121
|
+
end
|
122
|
+
|
123
|
+
def restore_with_nils(array, nils)
|
124
|
+
array = array.dup
|
125
|
+
nils.sort.each { |index| array.insert(index, nil) }
|
126
|
+
array
|
127
|
+
end
|
128
|
+
|
103
129
|
def options_for_multiple(data, key)
|
104
130
|
data.map do |item|
|
105
131
|
url_option_for(item, key)
|
@@ -119,7 +145,7 @@ class LHS::Record
|
|
119
145
|
def record_for_options(options)
|
120
146
|
records = []
|
121
147
|
if options.is_a?(Array)
|
122
|
-
options.each do |option|
|
148
|
+
options.compact.each do |option|
|
123
149
|
record = LHS::Record.for_url(option[:url])
|
124
150
|
next unless record
|
125
151
|
records.push(record)
|
@@ -143,7 +169,7 @@ class LHS::Record
|
|
143
169
|
|
144
170
|
def url_option_for(item, key)
|
145
171
|
link = item[key]
|
146
|
-
{ url: link.href }
|
172
|
+
return { url: link.href } if link.present? && link.href.present?
|
147
173
|
end
|
148
174
|
end
|
149
175
|
end
|
data/lib/lhs/data.rb
CHANGED
data/lib/lhs/record.rb
CHANGED
@@ -18,9 +18,7 @@ class LHS::Record
|
|
18
18
|
include Request
|
19
19
|
include Scope
|
20
20
|
|
21
|
-
delegate :_proxy, to: :_data
|
22
|
-
delegate :_endpoint, to: :_data
|
23
|
-
delegate :select, to: :_data
|
21
|
+
delegate :_proxy, :_endpoint, :merge_raw!, :select, to: :_data
|
24
22
|
|
25
23
|
def initialize(data = nil)
|
26
24
|
data = LHS::Data.new({}, nil, self.class) unless data
|
data/lib/lhs/version.rb
CHANGED
@@ -170,6 +170,59 @@ describe LHS::Record do
|
|
170
170
|
# rubocop:enable RSpec/InstanceVariable
|
171
171
|
end
|
172
172
|
end
|
173
|
+
|
174
|
+
context 'includes not present in response' do
|
175
|
+
before :each do
|
176
|
+
class Parent < LHS::Record
|
177
|
+
endpoint ':datastore/local-parents'
|
178
|
+
endpoint ':datastore/local-parents/:id'
|
179
|
+
end
|
180
|
+
|
181
|
+
class OptionalChild < LHS::Record
|
182
|
+
endpoint ':datastore/local-children/:id'
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'handles missing but included fields in single object response' do
|
187
|
+
stub_request(:get, "#{datastore}/local-parents/1")
|
188
|
+
.to_return(status: 200, body: {
|
189
|
+
'href' => "#{datastore}/local-parents/1",
|
190
|
+
'name' => 'RspecName'
|
191
|
+
}.to_json)
|
192
|
+
|
193
|
+
parent = Parent.includes(:optional_children).find(1)
|
194
|
+
expect(parent).not_to be nil
|
195
|
+
expect(parent.name).to eq 'RspecName'
|
196
|
+
expect(parent.optional_children).to be nil
|
197
|
+
end
|
198
|
+
|
199
|
+
it 'handles missing but included fields in collection response' do
|
200
|
+
stub_request(:get, "#{datastore}/local-parents")
|
201
|
+
.to_return(status: 200, body: {
|
202
|
+
items: [
|
203
|
+
{
|
204
|
+
'href' => "#{datastore}/local-parents/1",
|
205
|
+
'name' => 'RspecParent'
|
206
|
+
}, {
|
207
|
+
'href' => "#{datastore}/local-parents/2",
|
208
|
+
'name' => 'RspecParent2',
|
209
|
+
'optional_child' => {
|
210
|
+
'href' => "#{datastore}/local-children/1"
|
211
|
+
}
|
212
|
+
}]
|
213
|
+
}.to_json)
|
214
|
+
|
215
|
+
stub_request(:get, "#{datastore}/local-children/1")
|
216
|
+
.to_return(status: 200, body: {
|
217
|
+
href: "#{datastore}/local_children/1",
|
218
|
+
name: 'RspecOptionalChild1'
|
219
|
+
}.to_json)
|
220
|
+
|
221
|
+
child = Parent.includes(:optional_child).where[1].optional_child
|
222
|
+
expect(child).not_to be nil
|
223
|
+
expect(child.name).to eq 'RspecOptionalChild1'
|
224
|
+
end
|
225
|
+
end
|
173
226
|
end
|
174
227
|
|
175
228
|
context 'links pointing to nowhere' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lhs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- https://github.com/local-ch/lhs/graphs/contributors
|
@@ -343,7 +343,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
343
343
|
requirements:
|
344
344
|
- Ruby >= 1.9.2
|
345
345
|
rubyforge_project:
|
346
|
-
rubygems_version: 2.
|
346
|
+
rubygems_version: 2.5.1
|
347
347
|
signing_key:
|
348
348
|
specification_version: 4
|
349
349
|
summary: Rails gem providing an easy, active-record-like interface for http json services
|