lhs 14.2.0 → 14.3.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: 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