lhs 3.3.6 → 3.4.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 +19 -2
- data/lib/lhs/collection.rb +6 -5
- data/lib/lhs/concerns/item/destroy.rb +1 -2
- data/lib/lhs/concerns/item/save.rb +1 -1
- data/lib/lhs/concerns/item/update.rb +2 -3
- data/lib/lhs/concerns/item/validation.rb +1 -1
- data/lib/lhs/concerns/record/all.rb +16 -11
- data/lib/lhs/concerns/record/batch.rb +4 -4
- data/lib/lhs/concerns/record/configuration.rb +34 -0
- data/lib/lhs/concerns/record/create.rb +2 -2
- data/lib/lhs/concerns/record/endpoints.rb +1 -1
- data/lib/lhs/concerns/record/find.rb +2 -2
- data/lib/lhs/concerns/record/find_by.rb +1 -1
- data/lib/lhs/concerns/record/where.rb +1 -1
- data/lib/lhs/data.rb +8 -6
- data/lib/lhs/endpoint.rb +1 -1
- data/lib/lhs/proxy.rb +1 -2
- data/lib/lhs/record.rb +1 -0
- data/lib/lhs/version.rb +1 -1
- data/spec/collection/configurable_spec.rb +44 -0
- data/spec/data/collection_spec.rb +7 -1
- data/spec/data/raw_spec.rb +2 -5
- data/spec/data/select_spec.rb +7 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c6ba978add2aba0196bb5d98ecb6e114445db064
|
4
|
+
data.tar.gz: be48ebe2badd12166f55dac56e6579bef5fbed77
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e96f1f2d0baa2658854f73222e50a7569ccc5afd4075614eaadb99f656afbe041f839ca7332f358a41e7e3fad18d5f30e1b90724ba4dac5dd9969ca42ceab61a
|
7
|
+
data.tar.gz: 960bce0293960b60fd428d80d272038db342001416ab93cd00f5715e3a7eb1ee96d1f7d28456dbbc89163e2f3e81e6611060bb596be8040c060086794a0cf0ab
|
data/README.md
CHANGED
@@ -368,7 +368,24 @@ Feedback.where(limit: 50, offset: 51)
|
|
368
368
|
`limit` provides amount of items per page.
|
369
369
|
`offset` provides how many items where skipped to start the current page.
|
370
370
|
|
371
|
-
|
371
|
+
### Configure the name of the keys for offset, limit, total and name of items
|
372
|
+
|
373
|
+
Endpoints provide different interfaces to deal with paginated resources.
|
374
|
+
They differ for example for the key that is used for providing the current page items, the total amount of items, the current page size etc.
|
375
|
+
In order to have `LHS::Record` deal with those different interfaces you can configure it:
|
376
|
+
|
377
|
+
```ruby
|
378
|
+
class Search < LHS::Record
|
379
|
+
configuration items: :docs, limit: :size, offset: :start, total: :totalResults
|
380
|
+
endpoint ':search/:type'
|
381
|
+
end
|
382
|
+
```
|
383
|
+
`items` key used to determine items of the current page.
|
384
|
+
`limit` key used to work with page limits.
|
385
|
+
`offset` key used to paginate multiple pages.
|
386
|
+
`total` key used to determine the total amount of items.
|
387
|
+
|
388
|
+
### Partial Kaminari support
|
372
389
|
|
373
390
|
LHS implements an interface that makes it partially working with Kaminari.
|
374
391
|
|
@@ -384,7 +401,7 @@ For example, you can use kaminari to render paginations based on LHS Records:
|
|
384
401
|
= paginate @items
|
385
402
|
```
|
386
403
|
|
387
|
-
|
404
|
+
### form_for Helper
|
388
405
|
Rails `form_for` view-helper can be used in combination with instances of LHS::Record to autogenerate forms:
|
389
406
|
```
|
390
407
|
<%= form_for(@instance, url: '/create') do |f| %>
|
data/lib/lhs/collection.rb
CHANGED
@@ -7,17 +7,18 @@ class LHS::Collection < LHS::Proxy
|
|
7
7
|
include InternalCollection
|
8
8
|
|
9
9
|
delegate :select, to: :_collection
|
10
|
+
delegate :_record, to: :_data
|
10
11
|
|
11
12
|
def total
|
12
|
-
_data._raw[
|
13
|
+
_data._raw[_record.total_key]
|
13
14
|
end
|
14
15
|
|
15
16
|
def limit
|
16
|
-
_data._raw[
|
17
|
+
_data._raw[_record.limit_key]
|
17
18
|
end
|
18
19
|
|
19
20
|
def offset
|
20
|
-
_data._raw[
|
21
|
+
_data._raw[_record.offset_key]
|
21
22
|
end
|
22
23
|
|
23
24
|
def href
|
@@ -26,8 +27,8 @@ class LHS::Collection < LHS::Proxy
|
|
26
27
|
|
27
28
|
def _collection
|
28
29
|
raw = _data._raw if _data._raw.is_a?(Array)
|
29
|
-
raw ||= _data._raw[
|
30
|
-
Collection.new(raw, _data,
|
30
|
+
raw ||= _data._raw[_record.items_key]
|
31
|
+
Collection.new(raw, _data, _record)
|
31
32
|
end
|
32
33
|
|
33
34
|
delegate :_raw, to: :_data
|
@@ -7,8 +7,7 @@ class LHS::Item < LHS::Proxy
|
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
|
9
9
|
def destroy
|
10
|
-
|
11
|
-
_data._request = record.request(method: :delete, url: href)._request
|
10
|
+
_data._request = _data.class.request(method: :delete, url: href)._request
|
12
11
|
_data
|
13
12
|
end
|
14
13
|
end
|
@@ -14,9 +14,8 @@ class LHS::Item < LHS::Proxy
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def update!(params)
|
17
|
-
|
18
|
-
_data.
|
19
|
-
response_data = record.request(
|
17
|
+
_data.merge_raw!(LHS::Data.new(params, _data.parent, _data.class))
|
18
|
+
response_data = _data.class.request(
|
20
19
|
method: :post,
|
21
20
|
url: href,
|
22
21
|
body: _data.to_json,
|
@@ -30,7 +30,7 @@ class LHS::Item < LHS::Proxy
|
|
30
30
|
private
|
31
31
|
|
32
32
|
def validation_endpoint
|
33
|
-
endpoint = _data.
|
33
|
+
endpoint = _data._record.find_endpoint(_data._raw)
|
34
34
|
endpoint ||= LHS::Endpoint.for_url(_data.href) if _data.href
|
35
35
|
validates = endpoint.options && endpoint.options.fetch(:validates, false)
|
36
36
|
fail 'Endpoint does not support validations!' unless validates
|
@@ -5,6 +5,8 @@ class LHS::Record
|
|
5
5
|
module All
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
|
+
DEFAULT_LIMIT = 100
|
9
|
+
|
8
10
|
module ClassMethods
|
9
11
|
# Should be an edge case but sometimes all objects from a certain resource
|
10
12
|
# are required. In this case we load the first page with the default max limit,
|
@@ -12,12 +14,10 @@ class LHS::Record
|
|
12
14
|
# for the following pages and concatenate all the results in order to return
|
13
15
|
# all the objects for a given resource.
|
14
16
|
def all(params = {})
|
15
|
-
|
16
|
-
|
17
|
-
data
|
18
|
-
|
19
|
-
request_all_the_rest(data, all, params) if data._raw.is_a?(Hash) && data._raw[:total]
|
20
|
-
data._record_class.new(LHS::Data.new(all, nil, self))
|
17
|
+
limit = params[limit_key] || DEFAULT_LIMIT
|
18
|
+
data = request(params: params.merge(limit_key => limit))
|
19
|
+
request_all_the_rest(data, params) if data._raw.is_a?(Hash) && data._raw[total_key]
|
20
|
+
data._record.new(LHS::Data.new(data, nil, self))
|
21
21
|
end
|
22
22
|
|
23
23
|
private
|
@@ -26,18 +26,23 @@ class LHS::Record
|
|
26
26
|
if data._raw.is_a?(Array)
|
27
27
|
data._raw
|
28
28
|
else
|
29
|
-
data._raw[
|
29
|
+
data._raw[items_key]
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
def request_all_the_rest(data,
|
34
|
-
total_left = data._raw[
|
35
|
-
limit = data._raw[
|
33
|
+
def request_all_the_rest(data, params)
|
34
|
+
total_left = data._raw[total_key] - data.count
|
35
|
+
limit = data._raw[limit_key] || data.count
|
36
36
|
if limit > 0
|
37
37
|
requests = total_left / limit
|
38
38
|
requests.times do |i|
|
39
39
|
offset = limit * (i + 1) + 1
|
40
|
-
|
40
|
+
data._raw[items_key].concat all_items_from request(
|
41
|
+
params: params.merge(
|
42
|
+
data._record.limit_key => limit,
|
43
|
+
data._record.offset_key => offset
|
44
|
+
)
|
45
|
+
)
|
41
46
|
end
|
42
47
|
end
|
43
48
|
end
|
@@ -8,10 +8,10 @@ class LHS::Record
|
|
8
8
|
module ClassMethods
|
9
9
|
# Process single entries fetched in batches
|
10
10
|
def find_each(options = {})
|
11
|
-
find_in_batches(options) do |
|
12
|
-
|
13
|
-
item = LHS::Item.new(
|
14
|
-
yield new(LHS::Data.new(item,
|
11
|
+
find_in_batches(options) do |records|
|
12
|
+
records.each do |record|
|
13
|
+
item = LHS::Item.new(record)
|
14
|
+
yield new(LHS::Data.new(item, records._data, self))
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
class LHS::Record
|
4
|
+
|
5
|
+
# Allows configuring endpoints
|
6
|
+
# like which keys are used for the items, offset, total etc.
|
7
|
+
module Configuration
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
mattr_accessor :configuration
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def configuration(args)
|
14
|
+
@configuration ||= args.freeze || {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def items_key
|
18
|
+
@configuration.try(:[], :items) || :items
|
19
|
+
end
|
20
|
+
|
21
|
+
def limit_key
|
22
|
+
@configuration.try(:[], :limit) || :limit
|
23
|
+
end
|
24
|
+
|
25
|
+
def total_key
|
26
|
+
@configuration.try(:[], :total) || :total
|
27
|
+
end
|
28
|
+
|
29
|
+
def offset_key
|
30
|
+
@configuration.try(:[], :offset) || :offset
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -13,13 +13,13 @@ class LHS::Record
|
|
13
13
|
data = LHS::Data.new(json, nil, self, e.response.request)
|
14
14
|
item = LHS::Item.new(data)
|
15
15
|
item.errors = LHS::Errors.new(e.response)
|
16
|
-
data.
|
16
|
+
data._record.new(LHS::Data.new(item, data))
|
17
17
|
end
|
18
18
|
|
19
19
|
def create!(data = {})
|
20
20
|
url = compute_url!(data)
|
21
21
|
data = request(url: url, method: :post, body: data.to_json, headers: { 'Content-Type' => 'application/json' })
|
22
|
-
data.
|
22
|
+
data._record.new(data)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
@@ -31,7 +31,7 @@ class LHS::Record
|
|
31
31
|
|
32
32
|
def for_url(url)
|
33
33
|
return unless url
|
34
|
-
_template, record = LHS::Record::Endpoints.all.detect do |template,
|
34
|
+
_template, record = LHS::Record::Endpoints.all.detect do |template, _|
|
35
35
|
LHC::Endpoint.match?(url, template)
|
36
36
|
end
|
37
37
|
record
|
data/lib/lhs/data.rb
CHANGED
@@ -5,14 +5,16 @@ Dir[File.dirname(__FILE__) + '/concerns/data/*.rb'].each { |file| require file }
|
|
5
5
|
class LHS::Data
|
6
6
|
include Json
|
7
7
|
|
8
|
+
delegate :instance_methods, :items_key, :limit_key, :total_key, :offset_key, to: :class
|
9
|
+
|
8
10
|
# prevent clashing with attributes of underlying data
|
9
|
-
attr_accessor :_proxy, :_raw, :_parent, :
|
11
|
+
attr_accessor :_proxy, :_raw, :_parent, :_record, :_request
|
10
12
|
|
11
13
|
def initialize(input, parent = nil, record = nil, request = nil)
|
12
14
|
self._raw = raw_from_input(input)
|
13
|
-
self._proxy = proxy_from_input(input)
|
14
|
-
self._record_class = record
|
15
15
|
self._parent = parent
|
16
|
+
self._record = record
|
17
|
+
self._proxy = proxy_from_input(input)
|
16
18
|
self._request = request
|
17
19
|
end
|
18
20
|
|
@@ -30,7 +32,7 @@ class LHS::Data
|
|
30
32
|
end
|
31
33
|
|
32
34
|
def class
|
33
|
-
_root.
|
35
|
+
_root._record
|
34
36
|
end
|
35
37
|
|
36
38
|
# enforce internal data structure to have deep symbolized keys
|
@@ -50,14 +52,14 @@ class LHS::Data
|
|
50
52
|
end
|
51
53
|
|
52
54
|
def respond_to_missing?(name, include_all = false)
|
53
|
-
(root_item? &&
|
55
|
+
(root_item? && instance_methods.include?(name)) ||
|
54
56
|
_proxy.respond_to?(name, include_all)
|
55
57
|
end
|
56
58
|
|
57
59
|
private
|
58
60
|
|
59
61
|
def collection_proxy?(input)
|
60
|
-
!! (input.is_a?(Hash) && input[
|
62
|
+
!! (input.is_a?(Hash) && input[items_key]) || input.is_a?(Array) || _raw.is_a?(Array)
|
61
63
|
end
|
62
64
|
|
63
65
|
def root_item
|
data/lib/lhs/endpoint.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
class LHS::Endpoint
|
3
3
|
|
4
4
|
def self.for_url(url)
|
5
|
-
template, record = LHS::Record::Endpoints.all.detect do |template,
|
5
|
+
template, record = LHS::Record::Endpoints.all.detect do |template, _record|
|
6
6
|
LHC::Endpoint.match?(url, template)
|
7
7
|
end
|
8
8
|
record.endpoints.detect { |endpoint| endpoint.url == template } if record
|
data/lib/lhs/proxy.rb
CHANGED
@@ -17,8 +17,7 @@ class LHS::Proxy
|
|
17
17
|
|
18
18
|
def reload!
|
19
19
|
fail 'No href found' unless _data.href
|
20
|
-
|
21
|
-
data = record.request(url: _data.href, method: :get)
|
20
|
+
data = _data.class.request(url: _data.href, method: :get)
|
22
21
|
_data.merge_raw!(data)
|
23
22
|
self._loaded = true
|
24
23
|
self
|
data/lib/lhs/record.rb
CHANGED
data/lib/lhs/version.rb
CHANGED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
describe LHS::Collection do
|
4
|
+
let(:search) { 'http://local.ch/search' }
|
5
|
+
let(:limit) { 10 }
|
6
|
+
let(:total) { 20 }
|
7
|
+
let(:offset) { 0 }
|
8
|
+
let(:first_response_data) do
|
9
|
+
{
|
10
|
+
docs: (1..10).to_a,
|
11
|
+
start: offset,
|
12
|
+
size: limit,
|
13
|
+
totalResults: total
|
14
|
+
}
|
15
|
+
end
|
16
|
+
let(:second_response_data) do
|
17
|
+
{
|
18
|
+
docs: (11..20).to_a,
|
19
|
+
start: offset,
|
20
|
+
size: limit,
|
21
|
+
totalResults: total
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
before(:each) do
|
26
|
+
LHC.config.placeholder('search', search)
|
27
|
+
class Search < LHS::Record
|
28
|
+
configuration items: :docs, limit: :size, offset: :start, total: :totalResults
|
29
|
+
endpoint ':search/:type'
|
30
|
+
end
|
31
|
+
stub_request(:get, "http://local.ch/search/phonebook?size=10").to_return(body: first_response_data.to_json)
|
32
|
+
stub_request(:get, "http://local.ch/search/phonebook?size=10&start=11").to_return(body: second_response_data.to_json)
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'lets you configure how to deal with collections' do
|
36
|
+
it 'initalises and gives access to collections according to configuration' do
|
37
|
+
results = Search.all(type: :phonebook, size: 10)
|
38
|
+
expect(results.count).to eq total
|
39
|
+
expect(results.total).to eq total
|
40
|
+
expect(results.limit).to eq limit
|
41
|
+
expect(results.offset).to eq offset
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/spec/data/raw_spec.rb
CHANGED
@@ -10,15 +10,12 @@ describe LHS::Data do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
let(:data_from_raw) do
|
13
|
-
LHS::Data.new(
|
14
|
-
href: 'http://www.local.ch/v2/stuff',
|
15
|
-
id: '123123123'
|
16
|
-
)
|
13
|
+
LHS::Data.new({ href: 'http://www.local.ch/v2/stuff', id: '123123123' }, nil, Record)
|
17
14
|
end
|
18
15
|
|
19
16
|
let(:data_from_item) do
|
20
17
|
raw = { href: 'http://www.local.ch/v2/stuff' }
|
21
|
-
item = LHS::Item.new(LHS::Data.new(raw))
|
18
|
+
item = LHS::Item.new(LHS::Data.new(raw, nil, Record))
|
22
19
|
LHS::Data.new(item)
|
23
20
|
end
|
24
21
|
|
data/spec/data/select_spec.rb
CHANGED
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: 3.
|
4
|
+
version: 3.4.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-03-
|
11
|
+
date: 2016-03-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: lhc
|
@@ -186,6 +186,7 @@ files:
|
|
186
186
|
- lib/lhs/concerns/item/validation.rb
|
187
187
|
- lib/lhs/concerns/record/all.rb
|
188
188
|
- lib/lhs/concerns/record/batch.rb
|
189
|
+
- lib/lhs/concerns/record/configuration.rb
|
189
190
|
- lib/lhs/concerns/record/create.rb
|
190
191
|
- lib/lhs/concerns/record/endpoints.rb
|
191
192
|
- lib/lhs/concerns/record/find.rb
|
@@ -207,6 +208,7 @@ files:
|
|
207
208
|
- script/ci/build.sh
|
208
209
|
- spec/.DS_Store
|
209
210
|
- spec/collection/collection_items_spec.rb
|
211
|
+
- spec/collection/configurable_spec.rb
|
210
212
|
- spec/collection/delegate_spec.rb
|
211
213
|
- spec/collection/enumerable_spec.rb
|
212
214
|
- spec/collection/meta_data_spec.rb
|
@@ -331,6 +333,7 @@ summary: Rails gem providing an easy, active-record-like interface to use http b
|
|
331
333
|
services
|
332
334
|
test_files:
|
333
335
|
- spec/collection/collection_items_spec.rb
|
336
|
+
- spec/collection/configurable_spec.rb
|
334
337
|
- spec/collection/delegate_spec.rb
|
335
338
|
- spec/collection/enumerable_spec.rb
|
336
339
|
- spec/collection/meta_data_spec.rb
|