lhs 3.3.6 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e6e194ca0104d33690c704260ef36ef265ab9979
4
- data.tar.gz: 63de1464cea6731ab54c58e01c5ef46d74d6b46c
3
+ metadata.gz: c6ba978add2aba0196bb5d98ecb6e114445db064
4
+ data.tar.gz: be48ebe2badd12166f55dac56e6579bef5fbed77
5
5
  SHA512:
6
- metadata.gz: 71f0954b3bea0a23ba9f8c6169e86df4a92b4d81b8702f3634eeb770b9e989a0b4795703f2de97b533ffd521711fac0a54a5e540426978a55413c83c393f0cce
7
- data.tar.gz: 84ac812bc020fe427adc6d34ae0d87a1c528701b8cb644da0bfe50b613e7a12dd7eb0bcf00c5c8b046afb024fb6d112cd36cbe729dbb2f89c39479fa8bb0e66b
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
- ## Partial Kaminari support
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
- ## form_for Helper
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| %>
@@ -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[:total]
13
+ _data._raw[_record.total_key]
13
14
  end
14
15
 
15
16
  def limit
16
- _data._raw[:limit]
17
+ _data._raw[_record.limit_key]
17
18
  end
18
19
 
19
20
  def offset
20
- _data._raw[:offset]
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[:items]
30
- Collection.new(raw, _data, _data._record_class)
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
- record = _data._root._record_class
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,7 +14,7 @@ class LHS::Item < LHS::Proxy
14
14
  end
15
15
 
16
16
  def save!
17
- record = _data._root._record_class
17
+ record = _data.class
18
18
  data = _data._raw.dup
19
19
  url =
20
20
  if href.present?
@@ -14,9 +14,8 @@ class LHS::Item < LHS::Proxy
14
14
  end
15
15
 
16
16
  def update!(params)
17
- record = _data._root._record_class
18
- _data.merge_raw!(LHS::Data.new(params))
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._record_class.find_endpoint(_data._raw)
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
- all = []
16
- default_max_limit = 100
17
- data = request(params: params.merge(limit: default_max_limit))
18
- all.concat(all_items_from(data))
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[:items]
29
+ data._raw[items_key]
30
30
  end
31
31
  end
32
32
 
33
- def request_all_the_rest(data, all, params)
34
- total_left = data._raw[:total] - data.count
35
- limit = data._raw[:limit] || data.count
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
- all.concat request(params: params.merge(limit: limit, offset: offset))._raw[:items]
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 |data|
12
- data.each do |record|
13
- item = LHS::Item.new(LHS::Data.new(record, data, self))
14
- yield new(LHS::Data.new(item, data, self))
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._record_class.new(LHS::Data.new(item, 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._record_class.new(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, _record_class|
34
+ _template, record = LHS::Record::Endpoints.all.detect do |template, _|
35
35
  LHC::Endpoint.match?(url, template)
36
36
  end
37
37
  record
@@ -14,8 +14,8 @@ class LHS::Record
14
14
  else
15
15
  find_by_id(args)
16
16
  end
17
- return data unless data._record_class
18
- data._record_class.new(data)
17
+ return data unless data._record
18
+ data._record.new(data)
19
19
  end
20
20
 
21
21
  private
@@ -26,7 +26,7 @@ class LHS::Record
26
26
  if data._proxy.is_a?(LHS::Collection)
27
27
  data.first || fail(LHC::NotFound.new('No item was found.', data._request.response))
28
28
  else
29
- data._record_class.new(data)
29
+ data._record.new(data)
30
30
  end
31
31
  end
32
32
  end
@@ -9,7 +9,7 @@ class LHS::Record
9
9
  # Used to query data from the service.
10
10
  def where(params = {})
11
11
  data = request(params: params)
12
- data._record_class.new(data)
12
+ data._record.new(data)
13
13
  end
14
14
  end
15
15
  end
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, :_record_class, :_request
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._record_class
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? && _root._record_class.instance_methods.include?(name)) ||
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[:items]) || input.is_a?(Array) || _raw.is_a?(Array)
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, _record_class|
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
- record = _data._root._record_class
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
@@ -3,6 +3,7 @@ Dir[File.dirname(__FILE__) + '/concerns/record/*.rb'].each { |file| require file
3
3
  class LHS::Record
4
4
  include All
5
5
  include Batch
6
+ include Configuration
6
7
  include Create
7
8
  include Endpoints
8
9
  include Find
data/lib/lhs/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module LHS
2
- VERSION = "3.3.6"
2
+ VERSION = "3.4.0"
3
3
  end
@@ -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
@@ -6,7 +6,13 @@ describe LHS::Data do
6
6
  end
7
7
 
8
8
  let(:data) do
9
- LHS::Data.new(json)
9
+ LHS::Data.new(json, nil, Record)
10
+ end
11
+
12
+ before(:each) do
13
+ class Record < LHS::Record
14
+ endpoint ':datastore/v2/data'
15
+ end
10
16
  end
11
17
 
12
18
  context 'collections' do
@@ -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
 
@@ -6,7 +6,13 @@ describe LHS::Data do
6
6
  end
7
7
 
8
8
  let(:data) do
9
- LHS::Data.new(raw)
9
+ LHS::Data.new(raw, nil, Record)
10
+ end
11
+
12
+ before(:each) do
13
+ class Record < LHS::Record
14
+ endpoint ':datastore/v2/data'
15
+ end
10
16
  end
11
17
 
12
18
  context 'select' do
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.3.6
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-07 00:00:00.000000000 Z
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