lhs 14.2.0 → 14.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e02a2c879954de6557dc437da50cddf53fbcb054
4
- data.tar.gz: cf5c0881ae67770796703f483d3cdd3939a47425
3
+ metadata.gz: a6435e1ce72c8bd918fc9a4b1f5fde544c47ba90
4
+ data.tar.gz: f12a4d30361c30793c3a79b182be4acf9bd213f2
5
5
  SHA512:
6
- metadata.gz: 5309110a6cc3d2a6afae3562c1297cc25a85959c5bdc3b4b3b28742c0d515aca862dcbf5572691631318818ad7b1cae1c1e7db9b2f8eb9e92c50e1a364c8ff4d
7
- data.tar.gz: 8bae589cb78ec9f43df90df959aa113e81c9000814ae5d8157e96311e1912fbd169a475dd75a80431145769ca8fe961f1dc447beca8797d1b812fe905da7fd6c
6
+ metadata.gz: c40a3b2b6d1f0942837fae1e2e0ee44794708b51a4927e4b52c8d0771f05f442ebf8313d0658053cb8ee7114f23ffaf8c6f0cb780d44da1e5e6bea271c7b46cb
7
+ data.tar.gz: ab234e491cf9e16141610dc9f3d8bda6423757b96daf2ba992b68f91e972d053409adcf3cb15b90a15a41b6f7cfe8ea0eb0149b9f2cb4fad25b6ecc138ef9720
data/README.md CHANGED
@@ -696,6 +696,23 @@ record = Record.find('1z-5r1fkaj')
696
696
  record.update(recommended: false)
697
697
  ```
698
698
 
699
+ ## Partial Update
700
+
701
+ Often you just want to update a single attribute on an existing record. As ActiveRecord's `update_attribute` skips validation, which is unlikely with api services, and `update_attributes` is just an alias for `update`, LHS introduces `partial_update` for that matter.
702
+
703
+ `partial_update` will return false if persisting fails. `partial_update!` instead will an raise exception.
704
+
705
+ `partial_update` always updates the data of the local object first, before it tries to sync with an endpoint. So even if persisting fails, the local object is updated.
706
+
707
+ ```ruby
708
+ record = Record.find('1z-5r1fkaj')
709
+ record.partial_update(recommended: false)
710
+ # POST /records/1z-5r1fkaj
711
+ {
712
+ recommended: true
713
+ }
714
+ ```
715
+
699
716
  ## Becomes
700
717
 
701
718
  Based on [ActiveRecord's implementation](http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-becomes), LHS implements `becomes`, too.
@@ -978,7 +995,7 @@ location = Location.find(123)
978
995
  location.id # 123
979
996
  ```
980
997
 
981
- ### Configure complex accessors for nested data (EXPERIMENTAL)
998
+ ### Configure complex accessors for nested data
982
999
 
983
1000
  If items, limit, pagination, total etc. is nested in the responding objects, use complex data structures for configuring a record.
984
1001
 
@@ -1171,7 +1188,7 @@ end
1171
1188
  Add to your spec_helper.rb:
1172
1189
 
1173
1190
  ```ruby
1174
- require 'lhs/test/request_cycle_cache'
1191
+ require 'lhs/test/request_cycle_cache_helper'
1175
1192
  ```
1176
1193
 
1177
1194
  This will initialize a MemoryStore cache for LHC::Caching interceptor and resets the cache before every test.
@@ -34,11 +34,12 @@ class LHS::Item < LHS::Proxy
34
34
 
35
35
  def create_and_merge_data!(options)
36
36
  direct_response_data = record.request(options)
37
- _data.merge_raw!(direct_response_data)
37
+ nested_path = record.item_created_key ? record.item_created_key : nil
38
+ _data.merge_raw!(direct_response_data, nested_path)
38
39
  response_headers = direct_response_data._request.response.headers
39
40
  if response_headers && response_headers['Location']
40
41
  location_data = record.request(options.merge(url: response_headers['Location'], method: :get, body: nil))
41
- _data.merge_raw!(location_data)
42
+ _data.merge_raw!(location_data, nested_path)
42
43
  end
43
44
  true
44
45
  end
@@ -12,18 +12,34 @@ class LHS::Item < LHS::Proxy
12
12
  false
13
13
  end
14
14
 
15
- def update!(params, options = {})
15
+ def partial_update(params, options = nil)
16
+ update!(params, options, true)
17
+ rescue LHC::Error => e
18
+ self.errors = LHS::Problems::Errors.new(e.response, record)
19
+ false
20
+ end
21
+
22
+ def partial_update!(params, options = nil)
23
+ update!(params, options, true)
24
+ end
25
+
26
+ def update!(params, options = {}, partial_update = false)
16
27
  options ||= {}
17
- _data.merge_raw!(LHS::Data.new(params, _data.parent, record))
28
+ partial_data = LHS::Data.new(params, _data.parent, record)
29
+ nested_path = record.item_created_key ? record.item_created_key : nil
30
+ _data.merge_raw!(partial_data, nested_path)
31
+ data_sent = partial_update ? partial_data : _data
32
+ url = href || record.find_endpoint(id: id).compile(id: id)
18
33
  response_data = record.request(
19
34
  options.merge(
20
- method: :post,
21
- url: href,
22
- body: _data.to_json,
35
+ method: options.fetch(:method, :post),
36
+ url: url,
37
+ body: data_sent.to_json,
23
38
  headers: { 'Content-Type' => 'application/json' }
24
39
  )
25
40
  )
26
- _data.merge_raw!(response_data)
41
+ nested_path = record.item_created_key ? record.item_created_key : nil
42
+ _data.merge_raw!(response_data, nested_path)
27
43
  true
28
44
  end
29
45
  end
@@ -28,13 +28,11 @@ class LHS::Data
28
28
 
29
29
  # merging data
30
30
  # e.g. when loading remote data via link
31
- def merge_raw!(data)
31
+ def merge_raw!(data, nested_path = nil)
32
32
  return false if data.blank? || !data._raw.is_a?(Hash)
33
- if _record && _record.item_created_key
34
- _raw.merge! data._raw.dig(*_record.item_created_key)
35
- else
36
- _raw.merge! data._raw
37
- end
33
+ raw = data._raw.dig(*nested_path) if nested_path
34
+ raw ||= data._raw
35
+ _raw.merge! raw
38
36
  end
39
37
 
40
38
  def _root
@@ -1,3 +1,3 @@
1
1
  module LHS
2
- VERSION = '14.2.0'
2
+ VERSION = '14.3.0'
3
3
  end
@@ -241,7 +241,7 @@ describe LHS::Item do
241
241
  it 'does not raise an error when trying to find error record model name' do
242
242
  expect(lambda do
243
243
  record.reviews.first.errors[:name]
244
- end).not_to raise_error(NoMethodError)
244
+ end).not_to raise_error
245
245
  end
246
246
  end
247
247
 
@@ -0,0 +1,110 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHS::Item do
4
+ before(:each) do
5
+ class Record < LHS::Record
6
+ endpoint ':datastore/v2/:campaign_id/feedbacks'
7
+ endpoint ':datastore/v2/feedbacks'
8
+ end
9
+ end
10
+
11
+ let(:json) do
12
+ load_json(:feedbacks)
13
+ end
14
+
15
+ let(:data) do
16
+ LHS::Data.new(json, nil, Record)
17
+ end
18
+
19
+ let(:item) do
20
+ data[0]
21
+ end
22
+
23
+ context 'update' do
24
+ it 'persists changes on the backend' do
25
+ stub_request(:post, item.href)
26
+ .with(body: { name: 'Steve' }.to_json)
27
+ result = item.partial_update(name: 'Steve')
28
+ expect(result).to eq true
29
+ end
30
+
31
+ it 'returns false if persisting went wrong' do
32
+ stub_request(:post, item.href).to_return(status: 500)
33
+ result = item.partial_update(name: 'Steve')
34
+ expect(result).to eq false
35
+ end
36
+
37
+ it 'merges reponse data with object' do
38
+ stub_request(:post, item.href)
39
+ .to_return(status: 200, body: item._raw.merge(likes: 'Banana').to_json)
40
+ item.partial_update(name: 'Steve')
41
+ expect(item.name).to eq 'Steve'
42
+ expect(item.likes).to eq 'Banana'
43
+ end
44
+
45
+ it 'updates local version of an object even if BE request fails' do
46
+ stub_request(:post, item.href)
47
+ .to_return(status: 400, body: item._raw.merge(likes: 'Banana').to_json)
48
+ item.update(name: 'Andrea')
49
+ expect(item.name).to eq 'Andrea'
50
+ expect(item.likes).not_to eq 'Banana'
51
+ end
52
+ end
53
+
54
+ context 'update!' do
55
+ it 'raises if something goes wrong' do
56
+ stub_request(:post, item.href)
57
+ .with(body: { name: 'Steve' }.to_json)
58
+ .to_return(status: 500)
59
+ expect(-> { item.partial_update!(name: 'Steve') }).to raise_error LHC::ServerError
60
+ end
61
+ end
62
+
63
+ context 'records without hrefs and nested items' do
64
+
65
+ before(:each) do
66
+ class Location < LHS::Record
67
+ endpoint 'http://uberall/locations'
68
+ endpoint 'http://uberall/locations/:id'
69
+ end
70
+ end
71
+
72
+ it 'finds and compiles existing endpoints to determine update url' do
73
+ stub_request(:get, "http://uberall/locations/1").to_return(body: { id: 1 }.to_json)
74
+ stub_request(:post, "http://uberall/locations/1").to_return(body: { id: 1, listings: [{ directory: 'facebook' }] }.to_json)
75
+ location = Location.find(1)
76
+ location.partial_update(autoSync: true)
77
+ expect(location.autoSync).to eq true
78
+ expect(location.listings.first.directory).to eq 'facebook'
79
+ end
80
+
81
+ context 'records with nested items' do
82
+
83
+ before(:each) do
84
+ class Location < LHS::Record
85
+ endpoint 'http://uberall/locations'
86
+ endpoint 'http://uberall/locations/:id'
87
+ configuration item_created_key: [:response, :location], item_key: [:response, :location]
88
+ end
89
+ end
90
+
91
+ it 'finds and compiles existing endpoints to determine update url' do
92
+ stub_request(:get, "http://uberall/locations/1").to_return(body: { response: { location: { id: 1 } } }.to_json)
93
+ stub_request(:post, "http://uberall/locations/1").to_return(body: { response: { location: { id: 1, listings: [{ directory: 'facebook' }] } } }.to_json)
94
+ location = Location.find(1)
95
+ location.partial_update(autoSync: true)
96
+ expect(location.autoSync).to eq true
97
+ expect(location.listings.first.directory).to eq 'facebook'
98
+ end
99
+
100
+ it 'use given update http method' do
101
+ stub_request(:get, "http://uberall/locations/1").to_return(body: { response: { location: { id: 1 } } }.to_json)
102
+ stub_request(:patch, "http://uberall/locations/1").to_return(body: { response: { location: { id: 1, listings: [{ directory: 'facebook' }] } } }.to_json)
103
+ location = Location.find(1)
104
+ location.partial_update({ autoSync: true }, { method: :patch })
105
+ expect(location.autoSync).to eq true
106
+ expect(location.listings.first.directory).to eq 'facebook'
107
+ end
108
+ end
109
+ end
110
+ 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: 14.2.0
4
+ version: 14.3.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: 2017-09-26 00:00:00.000000000 Z
11
+ date: 2017-10-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lhc
@@ -331,6 +331,7 @@ files:
331
331
  - spec/item/getter_spec.rb
332
332
  - spec/item/internal_data_structure_spec.rb
333
333
  - spec/item/map_spec.rb
334
+ - spec/item/partial_update_spec.rb
334
335
  - spec/item/respond_to_spec.rb
335
336
  - spec/item/save_spec.rb
336
337
  - spec/item/setter_spec.rb
@@ -508,6 +509,7 @@ test_files:
508
509
  - spec/item/getter_spec.rb
509
510
  - spec/item/internal_data_structure_spec.rb
510
511
  - spec/item/map_spec.rb
512
+ - spec/item/partial_update_spec.rb
511
513
  - spec/item/respond_to_spec.rb
512
514
  - spec/item/save_spec.rb
513
515
  - spec/item/setter_spec.rb