lhs 5.7.1 → 6.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 +20 -5
- data/lhs.gemspec +4 -2
- data/lib/lhs/concerns/record/includes.rb +19 -6
- data/lib/lhs/concerns/record/request.rb +26 -14
- data/lib/lhs/version.rb +1 -1
- data/spec/proxy/load_spec.rb +18 -0
- data/spec/record/includes_spec.rb +30 -0
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1375879a321c15e499ad2871e21ab93cda9b386b
|
4
|
+
data.tar.gz: dfa739b88f8c0f26bd47ce4722a9d145fb479ecd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b457566f62fc9aae5f60287eae881b2a5cf2cf46c2de118a283b301d20b6d98126d93f816d46a70ed4714bb485dd0a2d971f022846864e91eb58764802779232
|
7
|
+
data.tar.gz: da2266a749937a72f6fb2510c054024c1f2171493a7a05c4cdf7321b4e2af45aaf67229adc756d9e4f7da7aedd360d47638a6a2fc56e7dadac947959561018bc
|
data/README.md
CHANGED
@@ -174,6 +174,7 @@ After fetching [single](#find-single-records) or [multiple](#find-multiple-recor
|
|
174
174
|
You can apply options to the request chain. Those options will be forwarded to the request perfomed by the chain/query.
|
175
175
|
|
176
176
|
```ruby
|
177
|
+
# Authenticate with OAuth
|
177
178
|
options = { auth: { bearer: '123456' } }
|
178
179
|
|
179
180
|
AuthenticatedRecord = Record.options(options)
|
@@ -365,22 +366,22 @@ After include:
|
|
365
366
|
|
366
367
|
When including linked resources with `includes`, known/defined services and endpoints are used to make those requests.
|
367
368
|
That also means that options for endpoints of linked resources are applied when requesting those in addition.
|
368
|
-
This allows you to include protected resources (e.g.
|
369
|
+
This allows you to include protected resources (e.g. Basic auth) as endpoint options for oauth authentication get applied.
|
369
370
|
|
370
371
|
The [Auth Inteceptor](https://github.com/local-ch/lhc-core-interceptors#auth-interceptor) from [lhc-core-interceptors](https://github.com/local-ch/lhc-core-interceptors) is used to configure the following endpoints.
|
371
372
|
|
372
373
|
```ruby
|
373
374
|
class Favorite < LHS::Record
|
374
375
|
|
375
|
-
endpoint ':datastore/:user_id/favorites', auth: {
|
376
|
-
endpoint ':datastore/:user_id/favorites/:id', auth: {
|
376
|
+
endpoint ':datastore/:user_id/favorites', auth: { basic: { username: 'steve', password: 'can' } }
|
377
|
+
endpoint ':datastore/:user_id/favorites/:id', auth: { basic: { username: 'steve', password: 'can' } }
|
377
378
|
|
378
379
|
end
|
379
380
|
|
380
381
|
class Place < LHS::Record
|
381
382
|
|
382
|
-
endpoint ':datastore/v2/places', auth: {
|
383
|
-
endpoint ':datastore/v2/places/:id', auth: {
|
383
|
+
endpoint ':datastore/v2/places', auth: { basic: { username: 'steve', password: 'can' } }
|
384
|
+
endpoint ':datastore/v2/places/:id', auth: { basic: { username: 'steve', password: 'can' } }
|
384
385
|
|
385
386
|
end
|
386
387
|
|
@@ -388,6 +389,16 @@ Favorite.includes(:place).where(user_id: current_user.id)
|
|
388
389
|
# Will include places and applies endpoint options to authenticate the request.
|
389
390
|
```
|
390
391
|
|
392
|
+
### Forward options used for request made to include referenced resources
|
393
|
+
|
394
|
+
Provide options to the requests made to include referenced resources:
|
395
|
+
|
396
|
+
```
|
397
|
+
|
398
|
+
Favorite.includes(:place).references(place: { auth: { bearer: '123' }})
|
399
|
+
|
400
|
+
```
|
401
|
+
|
391
402
|
## Map data
|
392
403
|
|
393
404
|
To influence how data is accessed/provied, you can use mappings to either map deep nested data or to manipulate data when its accessed. Simply create methods inside the LHS::Record. They can access underlying data:
|
@@ -629,3 +640,7 @@ The behaviour of `count` and `length` is based on ActiveRecord's behaviour.
|
|
629
640
|
`count` Determine the number of elements by taking the number of total elements that is provided by the endpoint/api.
|
630
641
|
|
631
642
|
`length` This returns the number of elements loaded from an endpoint/api. In case of paginated resources this can be different to count, as it depends on how many pages have been loaded.
|
643
|
+
|
644
|
+
## License
|
645
|
+
|
646
|
+
[GNU Affero General Public License Version 3.](https://www.gnu.org/licenses/agpl-3.0.en.html)
|
data/lhs.gemspec
CHANGED
@@ -17,8 +17,8 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.test_files = `git ls-files -- spec/*`.split("\n")
|
18
18
|
s.require_paths = ['lib']
|
19
19
|
|
20
|
-
s.requirements << 'Ruby >=
|
21
|
-
s.required_ruby_version = '>=
|
20
|
+
s.requirements << 'Ruby >= 2.0.0'
|
21
|
+
s.required_ruby_version = '>= 2.0.0'
|
22
22
|
|
23
23
|
s.add_dependency 'lhc', '>= 3.5.2'
|
24
24
|
s.add_dependency 'lhc-core-interceptors', '>= 2.0.1'
|
@@ -31,4 +31,6 @@ Gem::Specification.new do |s|
|
|
31
31
|
s.add_development_dependency 'pry-byebug'
|
32
32
|
s.add_development_dependency 'ciderizer'
|
33
33
|
s.add_development_dependency 'capybara'
|
34
|
+
|
35
|
+
s.license = 'GPL-3'
|
34
36
|
end
|
@@ -5,22 +5,35 @@ class LHS::Record
|
|
5
5
|
module Includes
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
|
+
included do
|
9
|
+
cattr_accessor :including, :referencing
|
10
|
+
end
|
11
|
+
|
8
12
|
module ClassMethods
|
9
|
-
def
|
10
|
-
|
13
|
+
def includes(*args)
|
14
|
+
class_clone_factory(args).tap do |class_clone|
|
15
|
+
class_clone.including = unfold_args(args)
|
16
|
+
end
|
11
17
|
end
|
12
18
|
|
13
|
-
def
|
14
|
-
|
19
|
+
def references(*args)
|
20
|
+
class_clone_factory(args).tap do |class_clone|
|
21
|
+
class_clone.referencing = unfold_args(args)
|
22
|
+
end
|
15
23
|
end
|
16
24
|
|
17
|
-
|
25
|
+
private
|
26
|
+
|
27
|
+
def unfold_args(args)
|
28
|
+
args.size == 1 ? args[0] : args
|
29
|
+
end
|
30
|
+
|
31
|
+
def class_clone_factory(args)
|
18
32
|
name = "#{self}#{args.object_id}"
|
19
33
|
constant = Object.const_set(name.demodulize, self.dup) # rubocop:disable Style/RedundantSelf
|
20
34
|
class_clone = constant
|
21
35
|
class_clone.endpoints = endpoints
|
22
36
|
class_clone.mapping = mapping
|
23
|
-
class_clone.including = args.size == 1 ? args[0] : args
|
24
37
|
class_clone
|
25
38
|
end
|
26
39
|
end
|
@@ -19,20 +19,19 @@ class LHS::Record
|
|
19
19
|
# Convert URLs in options to endpoint templates
|
20
20
|
def convert_options_to_endpoints(options)
|
21
21
|
if options.is_a?(Array)
|
22
|
-
options.map { |
|
22
|
+
options.map { |request_options| convert_options_to_endpoint(request_options) }
|
23
23
|
else
|
24
|
-
|
24
|
+
convert_options_to_endpoint(options)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
def
|
29
|
-
return unless
|
30
|
-
|
31
|
-
url = option[:url]
|
28
|
+
def convert_options_to_endpoint(options)
|
29
|
+
return unless options.present?
|
30
|
+
url = options[:url]
|
32
31
|
endpoint = LHS::Endpoint.for_url(url)
|
33
32
|
return unless endpoint
|
34
33
|
template = endpoint.url
|
35
|
-
new_options =
|
34
|
+
new_options = options.deep_merge(params: LHC::Endpoint.values_as_params(template, url))
|
36
35
|
new_options[:url] = template
|
37
36
|
new_options
|
38
37
|
end
|
@@ -80,17 +79,18 @@ class LHS::Record
|
|
80
79
|
end
|
81
80
|
end
|
82
81
|
|
83
|
-
def handle_includes(includes, data)
|
82
|
+
def handle_includes(includes, data, references = {})
|
83
|
+
references ||= {}
|
84
84
|
if includes.is_a? Hash
|
85
|
-
includes.each { |included, sub_includes| handle_include(included, data, sub_includes) }
|
85
|
+
includes.each { |included, sub_includes| handle_include(included, data, sub_includes, references[included]) }
|
86
86
|
elsif includes.is_a? Array
|
87
|
-
includes.each { |included| handle_includes(included, data) }
|
87
|
+
includes.each { |included| handle_includes(included, data, references[included]) }
|
88
88
|
else
|
89
|
-
handle_include(includes, data)
|
89
|
+
handle_include(includes, data, nil, references[includes])
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
93
|
-
def handle_include(included, data, sub_includes = nil)
|
93
|
+
def handle_include(included, data, sub_includes = nil, references = nil)
|
94
94
|
return if data.blank? || skip_loading_includes?(data, included)
|
95
95
|
options =
|
96
96
|
if data.collection?
|
@@ -100,10 +100,22 @@ class LHS::Record
|
|
100
100
|
else
|
101
101
|
url_option_for(data, included)
|
102
102
|
end
|
103
|
+
options = extend_with_references(options, references)
|
103
104
|
addition = load_include(options, data, sub_includes)
|
104
105
|
extend_raw_data!(data, addition, included)
|
105
106
|
end
|
106
107
|
|
108
|
+
# Extends request options with options provided for this reference
|
109
|
+
def extend_with_references(options, references)
|
110
|
+
return options unless references
|
111
|
+
options ||= {}
|
112
|
+
if options.is_a?(Array)
|
113
|
+
options.map { |request_options| request_options.merge(references) }
|
114
|
+
else
|
115
|
+
options.merge(references)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
107
119
|
def skip_loading_includes?(data, included)
|
108
120
|
if data.collection?
|
109
121
|
data.to_a.none? { |item| item[included].present? }
|
@@ -140,7 +152,7 @@ class LHS::Record
|
|
140
152
|
data = restore_with_nils(data, locate_nils(options)) # nil objects in data provide location information for mapping
|
141
153
|
unless data.empty?
|
142
154
|
data = LHS::Data.new(data, nil, self)
|
143
|
-
handle_includes(including, data) if including
|
155
|
+
handle_includes(including, data, referencing) if including
|
144
156
|
end
|
145
157
|
data
|
146
158
|
end
|
@@ -200,7 +212,7 @@ class LHS::Record
|
|
200
212
|
endpoint = find_endpoint(options[:params])
|
201
213
|
response = LHC.request(process_options(options, endpoint))
|
202
214
|
data = LHS::Data.new(response.body, nil, self, response.request, endpoint)
|
203
|
-
handle_includes(including, data) if including
|
215
|
+
handle_includes(including, data, referencing) if including
|
204
216
|
data
|
205
217
|
end
|
206
218
|
|
data/lib/lhs/version.rb
CHANGED
data/spec/proxy/load_spec.rb
CHANGED
@@ -42,4 +42,22 @@ describe LHS::Proxy do
|
|
42
42
|
.to raise_error LHC::NotFound
|
43
43
|
end
|
44
44
|
end
|
45
|
+
|
46
|
+
context 'endpoint options' do
|
47
|
+
before(:each) do
|
48
|
+
class AnotherRecord < LHS::Record
|
49
|
+
endpoint ':datastore/v2/feedbacks', params: { color: :blue }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
let(:record) do
|
54
|
+
AnotherRecord.new(href: 'http://datastore/v2/feedbacks')
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'applys endpoint options on load!' do
|
58
|
+
stub_request(:get, 'http://datastore/v2/feedbacks?color=blue')
|
59
|
+
.to_return(body: {}.to_json)
|
60
|
+
record.load!
|
61
|
+
end
|
62
|
+
end
|
45
63
|
end
|
@@ -336,4 +336,34 @@ describe LHS::Record do
|
|
336
336
|
expect(place.contracts.first.products.href).to eq "#{datastore}/place/1/contacts/1/products"
|
337
337
|
end
|
338
338
|
end
|
339
|
+
|
340
|
+
context 'includes with options' do
|
341
|
+
before(:each) do
|
342
|
+
class Customer < LHS::Record
|
343
|
+
endpoint ':datastore/customers/:id'
|
344
|
+
end
|
345
|
+
|
346
|
+
class Place < LHS::Record
|
347
|
+
endpoint ':datastore/places'
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
it 'forwards includes options to requests made for those includes' do
|
352
|
+
stub_request(:get, "#{datastore}/customers/1")
|
353
|
+
.to_return(body: {
|
354
|
+
'places' => {
|
355
|
+
'href' => "#{datastore}/places"
|
356
|
+
}
|
357
|
+
}.to_json)
|
358
|
+
stub_request(:get, "#{datastore}/places?forwarded_params=123")
|
359
|
+
.to_return(body: {
|
360
|
+
'items' => [{ id: 1 }]
|
361
|
+
}.to_json)
|
362
|
+
customer = Customer
|
363
|
+
.includes(:places)
|
364
|
+
.references(places: { params: { forwarded_params: 123 } })
|
365
|
+
.find(1)
|
366
|
+
expect(customer.places.first.id).to eq 1
|
367
|
+
end
|
368
|
+
end
|
339
369
|
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: 6.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: 2016-
|
11
|
+
date: 2016-08-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: lhc
|
@@ -328,7 +328,8 @@ files:
|
|
328
328
|
- spec/support/load_json.rb
|
329
329
|
- spec/views/form_for_spec.rb
|
330
330
|
homepage: https://github.com/local-ch/lhs
|
331
|
-
licenses:
|
331
|
+
licenses:
|
332
|
+
- GPL-3
|
332
333
|
metadata: {}
|
333
334
|
post_install_message:
|
334
335
|
rdoc_options: []
|
@@ -338,14 +339,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
338
339
|
requirements:
|
339
340
|
- - ">="
|
340
341
|
- !ruby/object:Gem::Version
|
341
|
-
version:
|
342
|
+
version: 2.0.0
|
342
343
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
343
344
|
requirements:
|
344
345
|
- - ">="
|
345
346
|
- !ruby/object:Gem::Version
|
346
347
|
version: '0'
|
347
348
|
requirements:
|
348
|
-
- Ruby >=
|
349
|
+
- Ruby >= 2.0.0
|
349
350
|
rubyforge_project:
|
350
351
|
rubygems_version: 2.2.2
|
351
352
|
signing_key:
|