lhs 24.0.0 → 24.1.0.pre.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.
- checksums.yaml +4 -4
- data/README.md +48 -0
- data/lib/lhs/concerns/collection/internal_collection.rb +17 -1
- data/lib/lhs/concerns/data/extend.rb +77 -0
- data/lib/lhs/concerns/record/request.rb +2 -70
- data/lib/lhs/data.rb +15 -0
- data/lib/lhs/version.rb +1 -1
- data/spec/record/compact_spec.rb +67 -0
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0098eb4147ef54ee7e80bb67e1a466c39165ef4b65ad2ac18f6a2c024ee2e9f7'
|
4
|
+
data.tar.gz: 853bd4e9697debd6c559d24d295019473793c3c5bcf4c1a3f5cdba3d966a743c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d3db0060e2155188d1697ec6e9c9000d05b13592d6a8ec7c5f952a28b25d1162f72c009f5f70375e06e67637a8d4e488e1946a161bda24513cbb1ea17fe626a3
|
7
|
+
data.tar.gz: aa448eeb65c3b13ba529040d79b4a3cb6ac31f3961cf407e6d72d6f69bdc3dfc5f543c8d02cd1a3d4932b6a57e0c26fabbd91f365f7629676445cbc328e93e42
|
data/README.md
CHANGED
@@ -2290,6 +2290,54 @@ feedback = Feedback
|
|
2290
2290
|
.find(12345)
|
2291
2291
|
```
|
2292
2292
|
|
2293
|
+
#### compact: Remove included resources that didn't return any records
|
2294
|
+
|
2295
|
+
In case you include nested data and ignored errors while including, it can happen that you get back a collection that contains data based on response errors:
|
2296
|
+
|
2297
|
+
```ruby
|
2298
|
+
# app/controllers/some_controller.rb
|
2299
|
+
|
2300
|
+
user = User
|
2301
|
+
.includes(:places)
|
2302
|
+
.references(places: { ignore: LHC::NotFound })
|
2303
|
+
.find(123)
|
2304
|
+
```
|
2305
|
+
|
2306
|
+
```
|
2307
|
+
GET http://service/users/123
|
2308
|
+
{ "places": { "href": "http://service/users/123/places" } }
|
2309
|
+
|
2310
|
+
GET http://service/users/123/places
|
2311
|
+
{ "items": [
|
2312
|
+
{ "href": "http://service/places/1" },
|
2313
|
+
{ "href": "http://service/places/2" }
|
2314
|
+
] }
|
2315
|
+
|
2316
|
+
GET http://service/places/1
|
2317
|
+
200 { "name": "Casa Ferlin" }
|
2318
|
+
|
2319
|
+
GET http://service/places/2
|
2320
|
+
404 { "status": 404, "error": "not found" }
|
2321
|
+
```
|
2322
|
+
|
2323
|
+
```ruby
|
2324
|
+
user.places[1] # { "status": 404, "error": "not found" }
|
2325
|
+
```
|
2326
|
+
|
2327
|
+
In order to exclude items from a collection which where not based on successful responses, use `.compact` or `.compact!`:
|
2328
|
+
|
2329
|
+
```ruby
|
2330
|
+
# app/controllers/some_controller.rb
|
2331
|
+
|
2332
|
+
user = User
|
2333
|
+
.includes(:places)
|
2334
|
+
.references(places: { ignore: LHC::NotFound })
|
2335
|
+
.find(123)
|
2336
|
+
places = user.places.compact
|
2337
|
+
|
2338
|
+
places # { "items": [ { "href": "http://service/places/1", "name": "Casa Ferlin" } ] }
|
2339
|
+
```
|
2340
|
+
|
2293
2341
|
### Record batch processing
|
2294
2342
|
|
2295
2343
|
**Be careful using methods for batch processing. They could result in a lot of HTTP requests!**
|
@@ -14,7 +14,7 @@ class LHS::Collection < LHS::Proxy
|
|
14
14
|
|
15
15
|
attr_accessor :raw
|
16
16
|
delegate :length, :size, :first, :last, :sample, :[], :present?, :blank?, :empty?,
|
17
|
-
:<<, :push,
|
17
|
+
:<<, :push, to: :raw
|
18
18
|
|
19
19
|
def initialize(raw, parent, record)
|
20
20
|
self.raw = raw
|
@@ -36,6 +36,22 @@ class LHS::Collection < LHS::Proxy
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
+
def compact
|
40
|
+
dup.tap do |collection|
|
41
|
+
collection.compact! if collection.raw.present?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def compact!
|
46
|
+
self.raw = raw.map do |item|
|
47
|
+
if item.is_a?(LHS::Data) && item._request && !item._request.response.success?
|
48
|
+
nil
|
49
|
+
else
|
50
|
+
item
|
51
|
+
end
|
52
|
+
end.compact
|
53
|
+
end
|
54
|
+
|
39
55
|
private
|
40
56
|
|
41
57
|
def cast_item(item)
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support'
|
4
|
+
|
5
|
+
class LHS::Data
|
6
|
+
|
7
|
+
module Extend
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
# Extends already fetched data (self) with additionally
|
11
|
+
# fetched data (addition) using the given key
|
12
|
+
def extend!(addition, key)
|
13
|
+
if collection?
|
14
|
+
extend_collection!(addition, key)
|
15
|
+
elsif self[key]._raw.is_a? Array
|
16
|
+
extend_array!(addition, key)
|
17
|
+
elsif item?
|
18
|
+
extend_item!(addition, key)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def extend_collection!(addition, key)
|
25
|
+
map do |item|
|
26
|
+
item_raw = item._raw[key]
|
27
|
+
item_raw.blank? ? [nil] : item_raw
|
28
|
+
end
|
29
|
+
.flatten
|
30
|
+
.each_with_index do |item, index|
|
31
|
+
item_addition = addition[index]
|
32
|
+
next if item_addition.nil? || item.nil?
|
33
|
+
if item_addition._raw.is_a?(Array)
|
34
|
+
item[items_key] ||= []
|
35
|
+
item[items_key].concat(item_addition._raw)
|
36
|
+
else
|
37
|
+
item.merge! item_addition._raw
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def extend_array!(addition, key)
|
43
|
+
self[key].zip(addition) do |item, additional_item|
|
44
|
+
item._raw.merge!(additional_item._raw) if additional_item.present?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def extend_item!(addition, key)
|
49
|
+
return if addition.nil?
|
50
|
+
if addition.collection?
|
51
|
+
extend_item_with_collection!(addition, key)
|
52
|
+
else # simple case merges hash into hash
|
53
|
+
_raw[key.to_sym].merge!(addition._raw)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def extend_item_with_collection!(addition, key)
|
58
|
+
target = self[key]
|
59
|
+
if target._raw.is_a? Array
|
60
|
+
self[key] = addition.map(&:_raw)
|
61
|
+
else # hash with items
|
62
|
+
extend_item_with_hash_containing_items!(target, addition)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def extend_item_with_hash_containing_items!(target, addition)
|
67
|
+
LHS::Collection.nest(input: target._raw, value: [], record: self) # inits the nested collection
|
68
|
+
if LHS::Collection.access(input: target._raw, record: self).empty?
|
69
|
+
LHS::Collection.nest(input: target._raw, value: addition.reject { |item| item.nil? }, record: self)
|
70
|
+
else
|
71
|
+
LHS::Collection.access(input: target._raw, record: self).each_with_index do |item, index|
|
72
|
+
item.merge!(addition[index])
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -98,74 +98,6 @@ class LHS::Record
|
|
98
98
|
)
|
99
99
|
end
|
100
100
|
|
101
|
-
# Extends existing raw data with additionaly fetched data
|
102
|
-
def extend_raw_data!(data, addition, key)
|
103
|
-
if data.collection?
|
104
|
-
extend_base_collection!(data, addition, key)
|
105
|
-
elsif data[key]._raw.is_a? Array
|
106
|
-
extend_base_array!(data, addition, key)
|
107
|
-
elsif data.item?
|
108
|
-
extend_base_item!(data, addition, key)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
def extend_base_collection!(data, addition, key)
|
113
|
-
data.map do |item|
|
114
|
-
item_raw = item._raw[key]
|
115
|
-
item_raw.blank? ? [nil] : item_raw
|
116
|
-
end
|
117
|
-
.flatten
|
118
|
-
.each_with_index do |item, index|
|
119
|
-
item_addition = addition[index]
|
120
|
-
next if item_addition.nil? || item.nil?
|
121
|
-
if item_addition._raw.is_a?(Array)
|
122
|
-
extend_base_collection_with_array!(item, item_addition._raw)
|
123
|
-
else
|
124
|
-
item.merge! item_addition._raw
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
def extend_base_collection_with_array!(item, addition)
|
130
|
-
item[items_key] ||= []
|
131
|
-
item[items_key].concat(addition)
|
132
|
-
end
|
133
|
-
|
134
|
-
def extend_base_array!(data, addition, key)
|
135
|
-
data[key].zip(addition) do |item, additional_item|
|
136
|
-
item._raw.merge!(additional_item._raw) if additional_item.present?
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
def extend_base_item!(data, addition, key)
|
141
|
-
return if addition.nil?
|
142
|
-
if addition.collection?
|
143
|
-
extend_base_item_with_collection!(data, addition, key)
|
144
|
-
else # simple case merges hash into hash
|
145
|
-
data._raw[key.to_sym].merge!(addition._raw)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
def extend_base_item_with_collection!(data, addition, key)
|
150
|
-
target = data[key]
|
151
|
-
if target._raw.is_a? Array
|
152
|
-
data[key] = addition.map(&:_raw)
|
153
|
-
else # hash with items
|
154
|
-
extend_base_item_with_hash_of_items!(target, addition)
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
def extend_base_item_with_hash_of_items!(target, addition)
|
159
|
-
LHS::Collection.nest(input: target._raw, value: [], record: self)
|
160
|
-
if LHS::Collection.access(input: target._raw, record: self).empty?
|
161
|
-
LHS::Collection.nest(input: target._raw, value: addition.compact.map(&:_raw), record: self)
|
162
|
-
else
|
163
|
-
LHS::Collection.access(input: target._raw, record: self).each_with_index do |item, index|
|
164
|
-
item.merge!(addition[index])
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
101
|
def handle_includes(includes, data, references = {})
|
170
102
|
references ||= {}
|
171
103
|
if includes.is_a? Hash
|
@@ -187,7 +119,7 @@ class LHS::Record
|
|
187
119
|
options = options_for_data(data, included)
|
188
120
|
options = extend_with_reference(options, reference)
|
189
121
|
addition = load_include(options, data, sub_includes, reference)
|
190
|
-
|
122
|
+
data.extend!(addition, included)
|
191
123
|
expand_addition!(data, included, options) unless expanded_data?(addition)
|
192
124
|
end
|
193
125
|
end
|
@@ -210,7 +142,7 @@ class LHS::Record
|
|
210
142
|
record = record_for_options(options) || self
|
211
143
|
options = convert_options_to_endpoints(options) if record_for_options(options)
|
212
144
|
expanded_data = record.request(options)
|
213
|
-
|
145
|
+
data.extend!(expanded_data, included)
|
214
146
|
end
|
215
147
|
|
216
148
|
def expanded_data?(addition)
|
data/lib/lhs/data.rb
CHANGED
@@ -6,6 +6,8 @@ class LHS::Data
|
|
6
6
|
'lhs/concerns/data/becomes'
|
7
7
|
autoload :Equality,
|
8
8
|
'lhs/concerns/data/equality'
|
9
|
+
autoload :Extend,
|
10
|
+
'lhs/concerns/data/extend'
|
9
11
|
autoload :Json,
|
10
12
|
'lhs/concerns/data/json'
|
11
13
|
autoload :ToHash,
|
@@ -13,6 +15,7 @@ class LHS::Data
|
|
13
15
|
|
14
16
|
include Becomes
|
15
17
|
include Equality
|
18
|
+
include Extend
|
16
19
|
include Json
|
17
20
|
include ToHash
|
18
21
|
include LHS::Inspect
|
@@ -30,6 +33,7 @@ class LHS::Data
|
|
30
33
|
self._proxy = proxy_from_input(input)
|
31
34
|
self._request = request
|
32
35
|
self._endpoint = endpoint
|
36
|
+
preserve_input_requests!(input)
|
33
37
|
end
|
34
38
|
|
35
39
|
# merging data
|
@@ -97,6 +101,17 @@ class LHS::Data
|
|
97
101
|
|
98
102
|
private
|
99
103
|
|
104
|
+
def preserve_input_requests!(input)
|
105
|
+
if input.is_a?(LHS::Data)
|
106
|
+
_request = input._request if _request.nil?
|
107
|
+
elsif input.is_a?(Array) && input.first.is_a?(LHS::Data)
|
108
|
+
input.each_with_index do |item, index|
|
109
|
+
next if item.nil?
|
110
|
+
self[index]._request = item._request
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
100
115
|
def collection_proxy?(input)
|
101
116
|
(input.is_a?(Hash) && LHS::Collection.access(input: input, record: _record)) ||
|
102
117
|
input.is_a?(Array) ||
|
data/lib/lhs/version.rb
CHANGED
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_helper'
|
4
|
+
|
5
|
+
describe LHS::Record do
|
6
|
+
before do
|
7
|
+
class Place < LHS::Record
|
8
|
+
endpoint 'http://datastore/places/{id}'
|
9
|
+
end
|
10
|
+
|
11
|
+
class User < LHS::Record
|
12
|
+
endpoint 'http://datastore/users/{id}'
|
13
|
+
end
|
14
|
+
|
15
|
+
stub_request(:get, 'http://datastore/users/123')
|
16
|
+
.to_return(status: 200, body: {
|
17
|
+
href: 'http://datastore/users/123',
|
18
|
+
places: { href: 'http://datastore/users/123/places' }
|
19
|
+
}.to_json)
|
20
|
+
|
21
|
+
stub_request(:get, 'http://datastore/users/123/places?limit=100')
|
22
|
+
.to_return(status: 200, body: {
|
23
|
+
href: 'http://datastore/users/123/places?offset=0&limit=100',
|
24
|
+
items: [
|
25
|
+
{
|
26
|
+
href: 'http://datastore/users/123/places/789'
|
27
|
+
}
|
28
|
+
],
|
29
|
+
total: 4,
|
30
|
+
offset: 0,
|
31
|
+
limit: 10
|
32
|
+
}.to_json)
|
33
|
+
|
34
|
+
stub_request(:get, 'http://datastore/users/123/places/789?limit=100')
|
35
|
+
.to_return(
|
36
|
+
status: 404,
|
37
|
+
body: {
|
38
|
+
status: 404,
|
39
|
+
message: 'The requested resource does not exist.'
|
40
|
+
}.to_json
|
41
|
+
)
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
let(:places) do
|
46
|
+
User
|
47
|
+
.includes(:places)
|
48
|
+
.references(places: { ignore: LHC::NotFound })
|
49
|
+
.find('123')
|
50
|
+
.places
|
51
|
+
end
|
52
|
+
|
53
|
+
context '.compact' do
|
54
|
+
|
55
|
+
it 'removes linked resouces which could not get fetched' do
|
56
|
+
expect(places.compact.length).to eq 0
|
57
|
+
expect(places.length).not_to eq 0 # leaves the original intact
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context '.compact!' do
|
62
|
+
it 'removes linked resouces which could not get fetched' do
|
63
|
+
expect(places.compact!.length).to eq 0
|
64
|
+
expect(places.length).to eq 0 # and changes the original intact
|
65
|
+
end
|
66
|
+
end
|
67
|
+
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: 24.0.
|
4
|
+
version: 24.1.0.pre.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-
|
11
|
+
date: 2020-08-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -274,6 +274,7 @@ files:
|
|
274
274
|
- lib/lhs/concerns/configuration.rb
|
275
275
|
- lib/lhs/concerns/data/becomes.rb
|
276
276
|
- lib/lhs/concerns/data/equality.rb
|
277
|
+
- lib/lhs/concerns/data/extend.rb
|
277
278
|
- lib/lhs/concerns/data/json.rb
|
278
279
|
- lib/lhs/concerns/data/to_hash.rb
|
279
280
|
- lib/lhs/concerns/inspect.rb
|
@@ -471,6 +472,7 @@ files:
|
|
471
472
|
- spec/record/attribute_assignment_spec.rb
|
472
473
|
- spec/record/build_spec.rb
|
473
474
|
- spec/record/cast_nested_data_spec.rb
|
475
|
+
- spec/record/compact_spec.rb
|
474
476
|
- spec/record/create_spec.rb
|
475
477
|
- spec/record/creation_failed_spec.rb
|
476
478
|
- spec/record/custom_setters_spec.rb
|
@@ -561,9 +563,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
561
563
|
version: 2.3.0
|
562
564
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
563
565
|
requirements:
|
564
|
-
- - "
|
566
|
+
- - ">"
|
565
567
|
- !ruby/object:Gem::Version
|
566
|
-
version:
|
568
|
+
version: 1.3.1
|
567
569
|
requirements:
|
568
570
|
- Ruby >= 2.3.0
|
569
571
|
rubygems_version: 3.0.6
|
@@ -699,6 +701,7 @@ test_files:
|
|
699
701
|
- spec/record/attribute_assignment_spec.rb
|
700
702
|
- spec/record/build_spec.rb
|
701
703
|
- spec/record/cast_nested_data_spec.rb
|
704
|
+
- spec/record/compact_spec.rb
|
702
705
|
- spec/record/create_spec.rb
|
703
706
|
- spec/record/creation_failed_spec.rb
|
704
707
|
- spec/record/custom_setters_spec.rb
|