lhs 22.0.0 → 23.0.2
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 +31 -2
- data/lhs.gemspec +2 -2
- data/lib/lhs/concerns/record/request.rb +18 -24
- 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/record/includes_first_page_spec.rb +14 -4
- data/spec/record/update_spec.rb +62 -0
- metadata +8 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4598d2f5041bf799a481dd7fb9ddbe6767acfdc799de851a7592228023d70f96
|
4
|
+
data.tar.gz: 3688dabba7d80461e187b93107ba785d081bedb8be8b008eadebe00c43513e72
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 73d23712b3ee30c3e55fb11f95be384144ff521580ddb1afd7c3e70694aa3c57778f6a5bf751576e9a633e53720419147aadb249c4d076b0428caa0d30617829
|
7
|
+
data.tar.gz: 95f2eb1975d019b0f5ea57e20225552c459c6784a9584f5a79d6c45a0e92d3fd42eebfdbd010d6f00350ab750bb447ae6b50133537cec002d3aa9f6ff3d8ac73
|
data/README.md
CHANGED
@@ -99,6 +99,8 @@ record.review # "Lunch was great
|
|
99
99
|
* [Change/Update existing records](#changeupdate-existing-records)
|
100
100
|
* [save](#save)
|
101
101
|
* [update](#update)
|
102
|
+
* [Directly via Record](#directly-via-record)
|
103
|
+
* [per Instance](#per-instance)
|
102
104
|
* [partial_update](#partial_update)
|
103
105
|
* [Endpoint url parameter injection during record creation/change](#endpoint-url-parameter-injection-during-record-creationchange)
|
104
106
|
* [Record validation](#record-validation)
|
@@ -119,8 +121,8 @@ record.review # "Lunch was great
|
|
119
121
|
* [Record getters](#record-getters)
|
120
122
|
* [Include linked resources (hyperlinks and hypermedia)](#include-linked-resources-hyperlinks-and-hypermedia)
|
121
123
|
* [Generate links from parameters](#generate-links-from-parameters)
|
122
|
-
* [Ensure the whole linked collection is included
|
123
|
-
* [Include the first linked page
|
124
|
+
* [Ensure the whole linked collection is included with includes](#ensure-the-whole-linked-collection-is-included-with-includes)
|
125
|
+
* [Include only the first linked page of a linked collection: includes_first_page](#include-only-the-first-linked-page-of-a-linked-collection-includes_first_page)
|
124
126
|
* [Include various levels of linked data](#include-various-levels-of-linked-data)
|
125
127
|
* [Identify and cast known records when including records](#identify-and-cast-known-records-when-including-records)
|
126
128
|
* [Apply options for requests performed to fetch included records](#apply-options-for-requests-performed-to-fetch-included-records)
|
@@ -152,6 +154,7 @@ record.review # "Lunch was great
|
|
152
154
|
|
153
155
|
|
154
156
|
|
157
|
+
|
155
158
|
## Installation/Startup checklist
|
156
159
|
|
157
160
|
- [ ] Install LHS gem, preferably via `Gemfile`
|
@@ -1607,6 +1610,21 @@ POST https://service.example.com/records/1z-5r1fkaj { body: "{ 'name': 'Starbuck
|
|
1607
1610
|
|
1608
1611
|
##### update
|
1609
1612
|
|
1613
|
+
###### Directly via Record
|
1614
|
+
|
1615
|
+
```ruby
|
1616
|
+
# app/controllers/some_controller.rb
|
1617
|
+
|
1618
|
+
Record.update(id: '1z-5r1fkaj', name: 'Steve')
|
1619
|
+
|
1620
|
+
```
|
1621
|
+
```
|
1622
|
+
GET https://service.example.com/records/1z-5r1fkaj
|
1623
|
+
{ name: 'Steve' }
|
1624
|
+
```
|
1625
|
+
|
1626
|
+
###### per Instance
|
1627
|
+
|
1610
1628
|
`update` persists the whole object after new parameters are applied through arguments.
|
1611
1629
|
|
1612
1630
|
`update` will return false if persisting fails. `update!` instead will raise an exception.
|
@@ -2261,6 +2279,17 @@ In parallel:
|
|
2261
2279
|
GET https://service.example.com/places/4 { headers: { 'Authentication': 'Bearer 123' } }
|
2262
2280
|
```
|
2263
2281
|
|
2282
|
+
Here is another example, if you want to ignore errors, that occure while you fetch included resources:
|
2283
|
+
|
2284
|
+
```ruby
|
2285
|
+
# app/controllers/some_controller.rb
|
2286
|
+
|
2287
|
+
feedback = Feedback
|
2288
|
+
.includes(campaign: :entry)
|
2289
|
+
.references(campaign: { ignored_errors: [LHC::NotFound] })
|
2290
|
+
.find(12345)
|
2291
|
+
```
|
2292
|
+
|
2264
2293
|
### Record batch processing
|
2265
2294
|
|
2266
2295
|
**Be careful using methods for batch processing. They could result in a lot of HTTP requests!**
|
data/lhs.gemspec
CHANGED
@@ -24,7 +24,7 @@ Gem::Specification.new do |s|
|
|
24
24
|
|
25
25
|
s.add_dependency 'activemodel'
|
26
26
|
s.add_dependency 'activesupport', '>= 4.2.11'
|
27
|
-
s.add_dependency 'lhc', '>=
|
27
|
+
s.add_dependency 'lhc', '>= 11.2.0', '< 12'
|
28
28
|
s.add_dependency 'local_uri'
|
29
29
|
|
30
30
|
s.add_development_dependency 'capybara'
|
@@ -39,5 +39,5 @@ Gem::Specification.new do |s|
|
|
39
39
|
s.add_development_dependency 'sprockets', '< 4'
|
40
40
|
s.add_development_dependency 'webmock'
|
41
41
|
|
42
|
-
s.license = 'GPL-3'
|
42
|
+
s.license = 'GPL-3.0'
|
43
43
|
end
|
@@ -138,6 +138,7 @@ class LHS::Record
|
|
138
138
|
end
|
139
139
|
|
140
140
|
def extend_base_item!(data, addition, key)
|
141
|
+
return if addition.nil?
|
141
142
|
if addition.collection?
|
142
143
|
extend_base_item_with_collection!(data, addition, key)
|
143
144
|
else # simple case merges hash into hash
|
@@ -187,7 +188,7 @@ class LHS::Record
|
|
187
188
|
options = extend_with_reference(options, reference)
|
188
189
|
addition = load_include(options, data, sub_includes, reference)
|
189
190
|
extend_raw_data!(data, addition, included)
|
190
|
-
expand_addition!(data, included, options)
|
191
|
+
expand_addition!(data, included, options) unless expanded_data?(addition)
|
191
192
|
end
|
192
193
|
end
|
193
194
|
|
@@ -205,28 +206,24 @@ class LHS::Record
|
|
205
206
|
def expand_addition!(data, included, reference)
|
206
207
|
addition = data[included]
|
207
208
|
options = options_for_data(addition)
|
208
|
-
options = extend_with_reference(options, reference
|
209
|
+
options = extend_with_reference(options, reference)
|
209
210
|
record = record_for_options(options) || self
|
210
211
|
options = convert_options_to_endpoints(options) if record_for_options(options)
|
211
|
-
expanded_data =
|
212
|
-
record.request(options)
|
213
|
-
rescue LHC::NotFound
|
214
|
-
LHS::Data.new({}, data, record)
|
215
|
-
end
|
212
|
+
expanded_data = record.request(options)
|
216
213
|
extend_raw_data!(data, expanded_data, included)
|
217
214
|
end
|
218
215
|
|
219
|
-
def
|
216
|
+
def expanded_data?(addition)
|
220
217
|
return false if addition.blank?
|
221
218
|
if addition.item?
|
222
|
-
(addition._raw.keys - [:href]).
|
219
|
+
(addition._raw.keys - [:href]).any?
|
223
220
|
elsif addition.collection?
|
224
|
-
addition.
|
221
|
+
addition.any? do |item|
|
225
222
|
next if item.blank?
|
226
223
|
if item._raw.is_a?(Hash)
|
227
|
-
(item._raw.keys - [:href]).
|
224
|
+
(item._raw.keys - [:href]).any?
|
228
225
|
elsif item._raw.is_a?(Array)
|
229
|
-
item.any? { |item| (item._raw.keys - [:href]).
|
226
|
+
item.any? { |item| (item._raw.keys - [:href]).any? }
|
230
227
|
end
|
231
228
|
end
|
232
229
|
end
|
@@ -234,7 +231,8 @@ class LHS::Record
|
|
234
231
|
|
235
232
|
# Extends request options with options provided for this reference
|
236
233
|
def extend_with_reference(options, reference)
|
237
|
-
return options
|
234
|
+
return options if reference.blank?
|
235
|
+
reference = reference.except(:url)
|
238
236
|
options ||= {}
|
239
237
|
if options.is_a?(Array)
|
240
238
|
options.map { |request_options| request_options.merge(reference) if request_options.present? }
|
@@ -348,18 +346,14 @@ class LHS::Record
|
|
348
346
|
end
|
349
347
|
|
350
348
|
# Load additional resources that are requested with include
|
351
|
-
def load_include(options,
|
349
|
+
def load_include(options, _data, sub_includes, references)
|
352
350
|
record = record_for_options(options) || self
|
353
351
|
options = convert_options_to_endpoints(options) if record_for_options(options)
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
load_include_simple!(options, record)
|
360
|
-
end
|
361
|
-
rescue LHC::NotFound
|
362
|
-
LHS::Data.new({}, data, record)
|
352
|
+
prepare_options_for_include_request!(options, sub_includes, references)
|
353
|
+
if references && references[:all] # include all linked resources
|
354
|
+
load_include_all!(options, record, sub_includes, references)
|
355
|
+
else # simply request first page/batch
|
356
|
+
load_include_simple!(options, record)
|
363
357
|
end
|
364
358
|
end
|
365
359
|
|
@@ -372,7 +366,7 @@ class LHS::Record
|
|
372
366
|
|
373
367
|
def load_include_simple!(options, record)
|
374
368
|
data = record.request(options)
|
375
|
-
warn "[WARNING] You included `#{options[:url]}`, 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)." if paginated?(data._raw)
|
369
|
+
warn "[WARNING] You included `#{options[:url]}`, 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)." if data && paginated?(data._raw)
|
376
370
|
data
|
377
371
|
end
|
378
372
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support'
|
4
|
+
|
5
|
+
class LHS::Record
|
6
|
+
|
7
|
+
module Update
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
included do
|
11
|
+
class <<self
|
12
|
+
alias_method :update, :create
|
13
|
+
alias_method :update!, :create!
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/lhs/record.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class LHS::Record
|
4
|
+
autoload :AttributeAssignment,
|
5
|
+
'lhs/concerns/record/attribute_assignment'
|
4
6
|
autoload :Batch,
|
5
7
|
'lhs/concerns/record/batch'
|
6
8
|
autoload :Chainable,
|
@@ -45,9 +47,10 @@ class LHS::Record
|
|
45
47
|
'lhs/concerns/record/scope'
|
46
48
|
autoload :Tracing,
|
47
49
|
'lhs/concerns/record/tracing'
|
48
|
-
autoload :
|
49
|
-
'lhs/concerns/record/
|
50
|
+
autoload :Update,
|
51
|
+
'lhs/concerns/record/update'
|
50
52
|
|
53
|
+
include AttributeAssignment
|
51
54
|
include Batch
|
52
55
|
include Chainable
|
53
56
|
include Configuration
|
@@ -72,7 +75,7 @@ class LHS::Record
|
|
72
75
|
include Relations
|
73
76
|
include Scope
|
74
77
|
include Tracing
|
75
|
-
include
|
78
|
+
include Update
|
76
79
|
|
77
80
|
delegate :_proxy, :_endpoint, :merge_raw!, :select, :becomes, :respond_to?, to: :_data
|
78
81
|
|
data/lib/lhs/version.rb
CHANGED
@@ -224,7 +224,7 @@ describe LHS::Record do
|
|
224
224
|
end
|
225
225
|
|
226
226
|
context 'links pointing to nowhere' do
|
227
|
-
|
227
|
+
before do
|
228
228
|
class Feedback < LHS::Record
|
229
229
|
endpoint '{+datastore}/feedbacks'
|
230
230
|
endpoint '{+datastore}/feedbacks/{id}'
|
@@ -238,10 +238,20 @@ describe LHS::Record do
|
|
238
238
|
|
239
239
|
stub_request(:get, "#{datastore}/content-ads/51dfc5690cf271c375c5a12d")
|
240
240
|
.to_return(status: 404)
|
241
|
+
end
|
242
|
+
|
243
|
+
it 'raises LHC::NotFound for links that cannot be included' do
|
244
|
+
expect(-> {
|
245
|
+
Feedback.includes_first_page(campaign: :entry).find(123)
|
246
|
+
}).to raise_error LHC::NotFound
|
247
|
+
end
|
241
248
|
|
242
|
-
|
243
|
-
|
244
|
-
|
249
|
+
it 'ignores LHC::NotFound for links that cannot be included if configured so with reference options' do
|
250
|
+
feedback = Feedback
|
251
|
+
.includes_first_page(campaign: :entry)
|
252
|
+
.references(campaign: { ignored_errors: [LHC::NotFound] })
|
253
|
+
.find(123)
|
254
|
+
expect(feedback.campaign._raw.keys.length).to eq 1
|
245
255
|
end
|
246
256
|
end
|
247
257
|
|
@@ -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.2
|
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
|
@@ -530,6 +531,7 @@ files:
|
|
530
531
|
- spec/record/to_hash_spec.rb
|
531
532
|
- spec/record/to_json_spec.rb
|
532
533
|
- spec/record/tracing_spec.rb
|
534
|
+
- spec/record/update_spec.rb
|
533
535
|
- spec/record/where_chains_spec.rb
|
534
536
|
- spec/record/where_spec.rb
|
535
537
|
- spec/record/where_values_hash_spec.rb
|
@@ -546,7 +548,7 @@ files:
|
|
546
548
|
- spec/views/form_for_spec.rb
|
547
549
|
homepage: https://github.com/local-ch/lhs
|
548
550
|
licenses:
|
549
|
-
- GPL-3
|
551
|
+
- GPL-3.0
|
550
552
|
metadata: {}
|
551
553
|
post_install_message:
|
552
554
|
rdoc_options: []
|
@@ -757,6 +759,7 @@ test_files:
|
|
757
759
|
- spec/record/to_hash_spec.rb
|
758
760
|
- spec/record/to_json_spec.rb
|
759
761
|
- spec/record/tracing_spec.rb
|
762
|
+
- spec/record/update_spec.rb
|
760
763
|
- spec/record/where_chains_spec.rb
|
761
764
|
- spec/record/where_spec.rb
|
762
765
|
- spec/record/where_values_hash_spec.rb
|