lhs 23.0.2 → 24.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4598d2f5041bf799a481dd7fb9ddbe6767acfdc799de851a7592228023d70f96
4
- data.tar.gz: 3688dabba7d80461e187b93107ba785d081bedb8be8b008eadebe00c43513e72
3
+ metadata.gz: 00243f3b3ea3dd2e97864c126dc7b8177c3f6e38cd217aba7c1a2843d9215d4c
4
+ data.tar.gz: 2c63934cbc1752513d1336997d2c9743c40b518d31b177d30f18a6ffe00ea99a
5
5
  SHA512:
6
- metadata.gz: 73d23712b3ee30c3e55fb11f95be384144ff521580ddb1afd7c3e70694aa3c57778f6a5bf751576e9a633e53720419147aadb249c4d076b0428caa0d30617829
7
- data.tar.gz: 95f2eb1975d019b0f5ea57e20225552c459c6784a9584f5a79d6c45a0e92d3fd42eebfdbd010d6f00350ab750bb447ae6b50133537cec002d3aa9f6ff3d8ac73
6
+ metadata.gz: 492a78447b6b7985bed8a82025a95551f94943f6e712d09863ca99d3952bb16a26da46a88d6fc1edc5cb744dae230eab22319a038c3a0e67e76747e406afd2aa
7
+ data.tar.gz: 274eacd3f4815d81514b7273d6613851be0eb6427cd7c9fca1c0a8105cd5a28e62e1f5b740ad31331446a10d2cfe6fdc13c64808fb957511cbcf6b4e7790dc99
data/README.md CHANGED
@@ -979,7 +979,7 @@ If you need to render some different view in Rails based on an LHS error raised
979
979
 
980
980
  def show
981
981
  @records = Record
982
- .handle(LHC::Error, ->(error){ handle_error(error) })
982
+ .rescue(LHC::Error, ->(error){ rescue_from(error) })
983
983
  .where(color: 'blue')
984
984
  render 'show'
985
985
  render_error if @error
@@ -987,7 +987,7 @@ end
987
987
 
988
988
  private
989
989
 
990
- def handle_error(error)
990
+ def rescue_from(error)
991
991
  @error = error
992
992
  nil
993
993
  end
@@ -1012,7 +1012,7 @@ If you want to inject values for the failing records, that might not have been f
1012
1012
  # app/controllers/some_controller.rb
1013
1013
 
1014
1014
  data = Record
1015
- .handle(LHC::Unauthorized, ->(response) { Record.new(name: 'unknown') })
1015
+ .rescue(LHC::Unauthorized, ->(response) { Record.new(name: 'unknown') })
1016
1016
  .find(1, 2, 3)
1017
1017
 
1018
1018
  data[1].name # 'unknown'
@@ -1698,7 +1698,7 @@ record.partial_update(recommended: true)
1698
1698
 
1699
1699
  ```
1700
1700
  ```
1701
- POST https://service.example.com/records/1z-5r1fkaj { body: "{ 'name': 'Starbucks', 'recommended': true }" }
1701
+ POST https://service.example.com/records/1z-5r1fkaj { body: "{ 'recommended': true }" }
1702
1702
  ```
1703
1703
 
1704
1704
  -> See [record validation](#record-validation) for how to handle validation errors when updating records.
@@ -2286,10 +2286,58 @@ Here is another example, if you want to ignore errors, that occure while you fet
2286
2286
 
2287
2287
  feedback = Feedback
2288
2288
  .includes(campaign: :entry)
2289
- .references(campaign: { ignored_errors: [LHC::NotFound] })
2289
+ .references(campaign: { ignore: LHC::NotFound })
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!**
@@ -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', '>= 11.2.0', '< 12'
27
+ s.add_dependency 'lhc', '>= 12.1.1', '< 13'
28
28
  s.add_dependency 'local_uri'
29
29
 
30
30
  s.add_development_dependency 'capybara'
@@ -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, :compact, to: :raw
17
+ :<<, :push, to: :raw
18
18
 
19
19
  def initialize(raw, parent, record)
20
20
  self.raw = raw
@@ -36,13 +36,37 @@ 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
+ cast_item(item)
51
+ end
52
+ end.compact
53
+ end
54
+
39
55
  private
40
56
 
41
57
  def cast_item(item)
42
- record_by_href = LHS::Record.for_url(item[:href]) if item[:href]
43
58
  data = LHS::Data.new(item, @parent, @record)
44
- return (record_by_href || @record).new(data) if record_by_href || @record
45
- data
59
+ (record_by_href(item) || @record)&.new(data) || data
60
+ end
61
+
62
+ def record_by_href(item)
63
+ return if plain_value?(item) || item[:href].blank?
64
+
65
+ LHS::Record.for_url(item[:href])
66
+ end
67
+
68
+ def plain_value?(item)
69
+ item.is_a?(String) || item.is_a?(Numeric) || item.is_a?(TrueClass) || item.is_a?(FalseClass)
46
70
  end
47
71
  end
48
72
  end
@@ -0,0 +1,83 @@
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
+ addition = cast_relation_class_for_extension(addition, key)
14
+ if collection?
15
+ extend_collection!(addition, key)
16
+ elsif self[key]._raw.is_a? Array
17
+ extend_array!(addition, key)
18
+ elsif item?
19
+ extend_item!(addition, key)
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def cast_relation_class_for_extension(addition, key)
26
+ return addition if _record.nil? || _record._relations.nil? || _record._relations[key].nil?
27
+ addition.becomes(_record._relations[key][:record_class_name].constantize, errors: addition.errors, warnings: addition.warnings)
28
+ end
29
+
30
+ def extend_collection!(addition, key)
31
+ map do |item|
32
+ item_raw = item._raw[key]
33
+ item_raw.blank? ? [nil] : item_raw
34
+ end
35
+ .flatten
36
+ .each_with_index do |item, index|
37
+ item_addition = addition[index]
38
+ next if item_addition.nil? || item.nil?
39
+ if item_addition._raw.is_a?(Array)
40
+ item[items_key] ||= []
41
+ item[items_key].concat(item_addition._raw)
42
+ else
43
+ item.merge! item_addition._raw
44
+ end
45
+ end
46
+ end
47
+
48
+ def extend_array!(addition, key)
49
+ self[key].zip(addition) do |item, additional_item|
50
+ item._raw.merge!(additional_item._raw) if additional_item.present?
51
+ end
52
+ end
53
+
54
+ def extend_item!(addition, key)
55
+ return if addition.nil?
56
+ if addition.collection?
57
+ extend_item_with_collection!(addition, key)
58
+ else # simple case merges hash into hash
59
+ _raw[key.to_sym].merge!(addition._raw)
60
+ end
61
+ end
62
+
63
+ def extend_item_with_collection!(addition, key)
64
+ target = self[key]
65
+ if target._raw.is_a? Array
66
+ self[key] = addition.map(&:_raw)
67
+ else # hash with items
68
+ extend_item_with_hash_containing_items!(target, addition)
69
+ end
70
+ end
71
+
72
+ def extend_item_with_hash_containing_items!(target, addition)
73
+ LHS::Collection.nest(input: target._raw, value: [], record: self) # inits the nested collection
74
+ if LHS::Collection.access(input: target._raw, record: self).empty?
75
+ LHS::Collection.nest(input: target._raw, value: addition.reject { |item| item.nil? }, record: self)
76
+ else
77
+ LHS::Collection.access(input: target._raw, record: self).each_with_index do |item, index|
78
+ item.merge!(addition[index])
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -52,7 +52,7 @@ class LHS::Record
52
52
  Chain.new(self, Pagination.new(per: argument))
53
53
  end
54
54
 
55
- def handle(error_class, handler)
55
+ def rescue(error_class, handler)
56
56
  Chain.new(self, ErrorHandling.new(error_class => handler))
57
57
  end
58
58
 
@@ -255,7 +255,7 @@ class LHS::Record
255
255
  push(Pagination.new(per: argument))
256
256
  end
257
257
 
258
- def handle(error_class, handler)
258
+ def rescue(error_class, handler)
259
259
  push(ErrorHandling.new(error_class => handler))
260
260
  end
261
261
 
@@ -348,8 +348,8 @@ class LHS::Record
348
348
  def resolved_options
349
349
  options = chain_options
350
350
  options = options.deep_merge(params: chain_parameters.merge(chain_pagination))
351
- options = options.merge(error_handler: chain_error_handler) if chain_error_handler.present?
352
- options = options.merge(ignored_errors: chain_ignored_errors) if chain_ignored_errors.present?
351
+ options = options.merge(rescue: chain_error_handler) if chain_error_handler.present?
352
+ options = options.merge(ignore: chain_ignored_errors) if chain_ignored_errors.present?
353
353
  options = options.merge(including: chain_includes) if chain_includes.present?
354
354
  options = options.merge(referencing: chain_references) if chain_references.present?
355
355
  options
@@ -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
- extend_raw_data!(data, addition, included)
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
- extend_raw_data!(data, expanded_data, included)
145
+ data.extend!(expanded_data, included)
214
146
  end
215
147
 
216
148
  def expanded_data?(addition)
@@ -504,7 +436,7 @@ class LHS::Record
504
436
  options = options.deep_dup
505
437
  options[:ignored_errors] = ignored_errors if ignored_errors.present?
506
438
  options[:params]&.deep_symbolize_keys!
507
- options[:error_handler] = merge_error_handlers(options[:error_handler]) if options[:error_handler]
439
+ options[:rescue] = merge_error_handlers(options[:rescue]) if options[:rescue]
508
440
  options = (provider_options || {})
509
441
  .deep_merge(endpoint.options || {})
510
442
  .deep_merge(options)
@@ -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) ||
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LHS
4
- VERSION = '23.0.2'
4
+ VERSION = '24.1.1'
5
5
  end
@@ -6,7 +6,7 @@ class ErrorHandlingWithChainsController < ApplicationController
6
6
  # in the view (during render 'show')
7
7
  def fetch_in_view
8
8
  @records = DummyRecord
9
- .handle(LHC::Error, ->(error) { handle_error(error) })
9
+ .rescue(LHC::Error, ->(error) { handle_error(error) })
10
10
  .where(color: 'blue')
11
11
  render 'show'
12
12
  render_error if @error
@@ -16,7 +16,7 @@ class ErrorHandlingWithChainsController < ApplicationController
16
16
  # before the view is rendered
17
17
  def fetch_in_controller
18
18
  @records = DummyRecord
19
- .handle(LHC::Error, ->(error) { handle_error(error) })
19
+ .rescue(LHC::Error, ->(error) { handle_error(error) })
20
20
  .where(color: 'blue').fetch
21
21
  render 'show'
22
22
  render_error if @error
@@ -0,0 +1,90 @@
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
+ endpoint 'http://datastore/users/{user_id}/places/{id}'
10
+
11
+ def display_name
12
+ "*#{name}*"
13
+ end
14
+ end
15
+
16
+ class User < LHS::Record
17
+ endpoint 'http://datastore/users/{id}'
18
+ end
19
+
20
+ stub_request(:get, 'http://datastore/users/123')
21
+ .to_return(status: 200, body: {
22
+ href: 'http://datastore/users/123',
23
+ places: { href: 'http://datastore/users/123/places' }
24
+ }.to_json)
25
+
26
+ stub_request(:get, 'http://datastore/users/123/places?limit=100')
27
+ .to_return(status: 200, body: {
28
+ href: 'http://datastore/users/123/places?offset=0&limit=100',
29
+ items: [
30
+ {
31
+ href: 'http://datastore/users/123/places/789'
32
+ }, {
33
+ href: 'http://datastore/users/123/places/790'
34
+ }
35
+ ],
36
+ total: 2,
37
+ offset: 0,
38
+ limit: 10
39
+ }.to_json)
40
+
41
+ stub_request(:get, 'http://datastore/users/123/places/789?limit=100')
42
+ .to_return(
43
+ body: {
44
+ href: 'http://datastore/users/123/places/789?limit=100',
45
+ name: 'Mc Donalds'
46
+ }.to_json
47
+ )
48
+
49
+ stub_request(:get, 'http://datastore/users/123/places/790?limit=100')
50
+ .to_return(
51
+ status: 404,
52
+ body: {
53
+ status: 404,
54
+ message: 'The requested resource does not exist.'
55
+ }.to_json
56
+ )
57
+
58
+ end
59
+
60
+ let(:places) do
61
+ User
62
+ .includes(:places)
63
+ .references(places: { ignore: LHC::NotFound })
64
+ .find('123')
65
+ .places
66
+ end
67
+
68
+ context '.compact' do
69
+ it 'removes linked resouces which could not get fetched' do
70
+ expect(places.compact.length).to eq 1
71
+ expect(places.length).not_to eq 1 # leaves the original intact
72
+ end
73
+ end
74
+
75
+ context 'record casting' do
76
+ let(:expected_display_name) { '*Mc Donalds*' }
77
+
78
+ it 'finds the right record class' do
79
+ expect(places.first.display_name).to eq expected_display_name
80
+ expect(places.compact.map(&:display_name)).to eq [expected_display_name]
81
+ end
82
+ end
83
+
84
+ context '.compact!' do
85
+ it 'removes linked resouces which could not get fetched' do
86
+ expect(places.compact!.length).to eq 1
87
+ expect(places.length).to eq 1 # and changes the original intact
88
+ end
89
+ end
90
+ end
@@ -15,14 +15,14 @@ describe LHS::Record do
15
15
 
16
16
  it 'allows to chain error handling' do
17
17
  expect {
18
- Record.where(color: 'blue').handle(LHC::Error, ->(_error) { handler.handle }).first
18
+ Record.where(color: 'blue').rescue(LHC::Error, ->(_error) { handler.handle }).first
19
19
  }.not_to raise_error
20
20
  expect(handler).to have_received(:handle)
21
21
  end
22
22
 
23
23
  it 'reraises in case chained error is not matched' do
24
24
  expect {
25
- Record.where(color: 'blue').handle(LHC::Conflict, ->(_error) { handler.handle }).first
25
+ Record.where(color: 'blue').rescue(LHC::Conflict, ->(_error) { handler.handle }).first
26
26
  }.to raise_error(LHC::Error)
27
27
  expect(handler).not_to have_received(:handle)
28
28
  end
@@ -30,8 +30,8 @@ describe LHS::Record do
30
30
  it 'calls all the handlers' do
31
31
  expect {
32
32
  Record.where(color: 'blue')
33
- .handle(LHC::Error, ->(_error) { handler.handle_1 })
34
- .handle(LHC::Error, ->(_error) { handler.handle_2 })
33
+ .rescue(LHC::Error, ->(_error) { handler.handle_1 })
34
+ .rescue(LHC::Error, ->(_error) { handler.handle_2 })
35
35
  .first
36
36
  }.not_to raise_error
37
37
  expect(handler).to have_received(:handle_1)
@@ -33,7 +33,7 @@ describe LHS::Record do
33
33
  it 'applies error handlers from the chain and returns whatever the error handler returns' do
34
34
  stub_request(:get, "http://datastore/records/2").to_return(status: 401)
35
35
  data = Record
36
- .handle(LHC::Unauthorized, ->(_response) { Record.new(name: 'unknown') })
36
+ .rescue(LHC::Unauthorized, ->(_response) { Record.new(name: 'unknown') })
37
37
  .find(1, 2, 3)
38
38
  expect(data[1].name).to eq 'unknown'
39
39
  end
@@ -25,7 +25,7 @@ describe LHS::Record do
25
25
 
26
26
  it 'allows to pass error_handling for includes to LHC' do
27
27
  handler = ->(_) { return { deleted: true } }
28
- record = Record.includes_first_page(:other).references(other: { error_handler: { LHC::NotFound => handler } }).find(id: 1)
28
+ record = Record.includes_first_page(:other).references(other: { rescue: { LHC::NotFound => handler } }).find(id: 1)
29
29
 
30
30
  expect(record.other.deleted).to be(true)
31
31
  end
@@ -249,7 +249,7 @@ describe LHS::Record do
249
249
  it 'ignores LHC::NotFound for links that cannot be included if configured so with reference options' do
250
250
  feedback = Feedback
251
251
  .includes_first_page(campaign: :entry)
252
- .references(campaign: { ignored_errors: [LHC::NotFound] })
252
+ .references(campaign: { ignore: [LHC::NotFound] })
253
253
  .find(123)
254
254
  expect(feedback.campaign._raw.keys.length).to eq 1
255
255
  end
@@ -8,6 +8,14 @@ describe LHS::Record do
8
8
  class Customer < LHS::Record
9
9
  endpoint 'http://datastore/customers/{id}'
10
10
  end
11
+
12
+ class User < LHS::Record
13
+ endpoint 'http://datastore/users/{id}'
14
+ endpoint 'http://datastore/customers/{customer_id}/users/{id}'
15
+ def reversed_name
16
+ name.split.reverse.join(' ')
17
+ end
18
+ end
11
19
  end
12
20
 
13
21
  let!(:customer_request) do
@@ -18,6 +26,9 @@ describe LHS::Record do
18
26
  },
19
27
  'contact_addresses' => {
20
28
  'href' => "http://datastore/contact_addresses"
29
+ },
30
+ 'users' => {
31
+ 'href' => 'http://datastore/customers/1/users'
21
32
  }
22
33
  }.to_json)
23
34
  end
@@ -49,5 +60,37 @@ describe LHS::Record do
49
60
  assert_requested(electronic_addresses_request)
50
61
  assert_requested(contact_addresses_request)
51
62
  end
63
+
64
+ describe 'mapping related classes correctly' do
65
+ before do
66
+ stub_request(:get, 'http://datastore/customers/1/users?limit=100').to_return(
67
+ status: 200,
68
+ body: {
69
+ href: 'http://datastore/customers/1/users?offset=0&limit=100',
70
+ items: [
71
+ { href: 'http://datastore/customers/1/users/1' }
72
+ ],
73
+ total: 1,
74
+ offset: 0,
75
+ limit: 10
76
+ }.to_json
77
+ )
78
+
79
+ stub_request(:get, 'http://datastore/customers/1/users/1?limit=100')
80
+ .with(headers: { 'Authentication' => 'Bearer 123' })
81
+ .to_return(body: { href: 'http://datastore/users/1', name: 'Elizabeth Baker' }.to_json)
82
+ end
83
+
84
+ it 'maps correctly' do
85
+ users = Customer
86
+ .includes(:users)
87
+ .references(users: referencing_options)
88
+ .find(1)
89
+ .users
90
+
91
+ expect(users.first.reversed_name).to be_present
92
+ end
93
+ end
94
+
52
95
  end
53
96
  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: 23.0.2
4
+ version: 24.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - https://github.com/local-ch/lhs/graphs/contributors
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-13 00:00:00.000000000 Z
11
+ date: 2020-08-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -44,20 +44,20 @@ dependencies:
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 11.2.0
47
+ version: 12.1.1
48
48
  - - "<"
49
49
  - !ruby/object:Gem::Version
50
- version: '12'
50
+ version: '13'
51
51
  type: :runtime
52
52
  prerelease: false
53
53
  version_requirements: !ruby/object:Gem::Requirement
54
54
  requirements:
55
55
  - - ">="
56
56
  - !ruby/object:Gem::Version
57
- version: 11.2.0
57
+ version: 12.1.1
58
58
  - - "<"
59
59
  - !ruby/object:Gem::Version
60
- version: '12'
60
+ version: '13'
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: local_uri
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -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
@@ -550,7 +552,7 @@ homepage: https://github.com/local-ch/lhs
550
552
  licenses:
551
553
  - GPL-3.0
552
554
  metadata: {}
553
- post_install_message:
555
+ post_install_message:
554
556
  rdoc_options: []
555
557
  require_paths:
556
558
  - lib
@@ -566,8 +568,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
566
568
  version: '0'
567
569
  requirements:
568
570
  - Ruby >= 2.3.0
569
- rubygems_version: 3.0.6
570
- signing_key:
571
+ rubygems_version: 3.0.3
572
+ signing_key:
571
573
  specification_version: 4
572
574
  summary: 'REST services accelerator: Rails gem providing an easy, active-record-like
573
575
  interface for http (hypermedia) json services'
@@ -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