lhs 2.2.2 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +296 -30
- data/lhs.gemspec +3 -3
- data/lib/lhs.rb +0 -7
- data/lib/lhs/collection.rb +4 -4
- data/lib/lhs/concerns/item/destroy.rb +2 -2
- data/lib/lhs/concerns/item/save.rb +3 -3
- data/lib/lhs/concerns/item/update.rb +2 -2
- data/lib/lhs/concerns/item/validation.rb +4 -5
- data/lib/lhs/concerns/{service → record}/all.rb +2 -2
- data/lib/lhs/concerns/{service → record}/batch.rb +3 -3
- data/lib/lhs/concerns/{service → record}/create.rb +4 -3
- data/lib/lhs/concerns/{service → record}/endpoints.rb +6 -6
- data/lib/lhs/concerns/{service → record}/find.rb +3 -2
- data/lib/lhs/concerns/{service → record}/find_by.rb +3 -2
- data/lib/lhs/concerns/{service → record}/first.rb +1 -1
- data/lib/lhs/concerns/{service → record}/includes.rb +4 -2
- data/lib/lhs/concerns/{service → record}/mapping.rb +1 -1
- data/lib/lhs/concerns/{service → record}/model.rb +1 -1
- data/lib/lhs/concerns/{service → record}/request.rb +12 -12
- data/lib/lhs/concerns/{service → record}/where.rb +3 -2
- data/lib/lhs/data.rb +25 -53
- data/lib/lhs/endpoint.rb +2 -2
- data/lib/lhs/item.rb +8 -2
- data/lib/lhs/proxy.rb +2 -2
- data/lib/lhs/record.rb +42 -0
- data/lib/lhs/version.rb +1 -1
- data/spec/collection/meta_data_spec.rb +2 -2
- data/spec/collection/without_object_items_spec.rb +1 -1
- data/spec/data/item_spec.rb +2 -14
- data/spec/data/merge_spec.rb +3 -3
- data/spec/data/raw_spec.rb +1 -1
- data/spec/data/respond_to_spec.rb +3 -3
- data/spec/data/root_spec.rb +2 -2
- data/spec/data/to_json_spec.rb +2 -2
- data/spec/endpoint/for_url_spec.rb +1 -1
- data/spec/item/delegate_spec.rb +2 -2
- data/spec/item/destroy_spec.rb +4 -4
- data/spec/item/errors_spec.rb +4 -4
- data/spec/item/getter_spec.rb +2 -2
- data/spec/item/internal_data_structure_spec.rb +1 -1
- data/spec/item/save_spec.rb +3 -4
- data/spec/item/setter_spec.rb +2 -2
- data/spec/item/update_spec.rb +2 -2
- data/spec/item/validation_spec.rb +47 -75
- data/spec/proxy/load_spec.rb +2 -2
- data/spec/{service → record}/all_spec.rb +7 -7
- data/spec/{service → record}/build_spec.rb +5 -4
- data/spec/{service → record}/create_spec.rb +6 -5
- data/spec/{service → record}/creation_failed_spec.rb +6 -5
- data/spec/record/definitions_spec.rb +29 -0
- data/spec/{service → record}/endpoint_misconfiguration_spec.rb +3 -3
- data/spec/{service → record}/endpoint_options_spec.rb +4 -4
- data/spec/{service → record}/endpoints_spec.rb +15 -15
- data/spec/{service → record}/find_by_spec.rb +8 -8
- data/spec/{service → record}/find_each_spec.rb +3 -3
- data/spec/{service → record}/find_in_batches_spec.rb +6 -6
- data/spec/{service → record}/find_spec.rb +10 -9
- data/spec/{service → record}/first_spec.rb +7 -6
- data/spec/{service → record}/includes_spec.rb +7 -7
- data/spec/{service → record}/mapping_spec.rb +27 -16
- data/spec/{service → record}/model_name_spec.rb +2 -2
- data/spec/{service → record}/new_spec.rb +4 -3
- data/spec/{service → record}/request_spec.rb +3 -3
- data/spec/record/where_spec.rb +34 -0
- data/spec/support/cleanup_endpoints.rb +1 -1
- data/spec/support/{cleanup_services.rb → cleanup_records.rb} +2 -2
- metadata +60 -67
- data/docs/collections.md +0 -28
- data/docs/data.md +0 -39
- data/docs/items.md +0 -79
- data/docs/service.jpg +0 -0
- data/docs/service.pdf +2 -650
- data/docs/services.md +0 -266
- data/lib/lhs/concerns/service/build.rb +0 -19
- data/lib/lhs/service.rb +0 -18
- data/spec/data/pagination_spec.rb +0 -60
- data/spec/dummy/README.rdoc +0 -28
- data/spec/service/where_spec.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 23beb0804ec8b041eaa4e920e395a5d9b2bf394f
|
4
|
+
data.tar.gz: 3329ba17fc8d206210d143a8b8ad4aae09561316
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 451e95f0aa50d9f41eedd21f7339f36904d146f36c3ca880effe675f5b9b7c6a6198592e4a4d6e2c284a10fadbe4b7aa8a96b3f1e60748fae1988bc4e805f788
|
7
|
+
data.tar.gz: df8f2a78480a2ead8098c786e04f620e6541420c78803adaf2ee2524c31274a2ddd756d6dd4b7309d08c76cacea9bda907c797a1b6a346e3c2ecdf59a04ae45b
|
data/README.md
CHANGED
@@ -3,65 +3,331 @@ LHS
|
|
3
3
|
|
4
4
|
LHS uses [LHC](//github.com/local-ch/LHC) for http requests.
|
5
5
|
|
6
|
-
##
|
7
|
-
|
6
|
+
## Very Short Introduction
|
7
|
+
|
8
|
+
A LHS::Record makes data available using backend services and one or multiple endpoints.
|
8
9
|
|
9
10
|
```ruby
|
10
|
-
class Feedback < LHS::
|
11
|
+
class Feedback < LHS::Record
|
11
12
|
|
12
13
|
endpoint ':datastore/v2/content-ads/:campaign_id/feedbacks'
|
13
14
|
endpoint ':datastore/v2/feedbacks'
|
14
15
|
|
15
16
|
end
|
16
17
|
|
17
|
-
|
18
|
+
feedback = Feedback.find_by_email('somebody@mail.com') #<Feedback>
|
19
|
+
feedback.review # "Lunch was great"
|
18
20
|
```
|
19
21
|
|
20
|
-
|
22
|
+
## Where to store LHS::Records
|
23
|
+
|
24
|
+
Please store all defined LHS::Records in `app/models` as they are not autoloaded by rails otherwise.
|
25
|
+
|
26
|
+
## Endpoints
|
27
|
+
|
28
|
+
You setup a LHS::Record by configuring one or multiple backend endpoints. You can also add request options for an endpoint (see following example).
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
class Feedback < LHS::Record
|
32
|
+
|
33
|
+
endpoint ':datastore/v2/content-ads/:campaign_id/feedbacks'
|
34
|
+
endpoint ':datastore/v2/content-ads/:campaign_id/feedbacks/:id'
|
35
|
+
endpoint ':datastore/v2/feedbacks', cache: true, cache_expires_in: 1.day
|
36
|
+
endpoint ':datastore/v2/feedbacks/:id', cache: true, cache_expires_in: 1.day
|
37
|
+
|
38
|
+
end
|
39
|
+
```
|
21
40
|
|
22
|
-
|
23
|
-
An instance of LHS::Data contains raw data (json) and a proxy that is used to access data.
|
41
|
+
If you try to setup a LHS::Record with clashing endpoints it will immediately raise an exception.
|
24
42
|
|
25
43
|
```ruby
|
26
|
-
|
27
|
-
|
44
|
+
class Feedback < LHS::Record
|
45
|
+
|
46
|
+
endpoint ':datastore/v2/reviews'
|
47
|
+
endpoint ':datastore/v2/feedbacks'
|
48
|
+
|
49
|
+
end
|
50
|
+
# raises: Clashing endpoints.
|
28
51
|
```
|
29
52
|
|
30
|
-
|
53
|
+
## Find multiple records
|
54
|
+
|
55
|
+
You can query a backend service to provide records by using `where`.
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
Feedback.where(has_reviews: true)
|
59
|
+
```
|
60
|
+
|
61
|
+
This uses the `:datastore/v2/feedbacks` endpoint, cause `:campaign_id` was not provided. In addition it would add `?has_reviews=true` to the get parameters.
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
Feedback.where(campaign_id: 'fq-a81ngsl1d')
|
65
|
+
```
|
66
|
+
|
67
|
+
Uses the `:datastore/v2/content-ads/:campaign_id/feedbacks` endpoint.
|
68
|
+
|
69
|
+
## Find single records
|
70
|
+
|
71
|
+
`find` finds a unique record by uniqe identifier (usualy id).
|
72
|
+
|
73
|
+
If no record is found an error is raised.
|
31
74
|
|
32
75
|
## Proxy
|
33
|
-
|
76
|
+
Instead of mapping data when it arrives from the backend, the proxy makes data accessible when you access it, not when you fetch it. The proxy is used to access data and it is divided in `Collection` and `Item`.
|
77
|
+
|
78
|
+
`find` can also be used to find a single uniqe record with parameters:
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
Feedback.find(campaign_id: 123, id: 456)
|
82
|
+
```
|
83
|
+
|
84
|
+
`find_by` finds the first record matching the specified conditions.
|
85
|
+
|
86
|
+
If no record is found, `nil` is returned.
|
87
|
+
|
88
|
+
`find_by!` raises LHC::NotFound if nothing was found.
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
Feedback.find_by(id: 'z12f-3asm3ngals')
|
92
|
+
Feedback.find_by(id: 'doesntexist') # nil
|
93
|
+
```
|
94
|
+
|
95
|
+
`first` is an alias for finding the first record without parameters.
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
Feedback.first
|
99
|
+
```
|
100
|
+
|
101
|
+
If no record is found, `nil` is returned.
|
102
|
+
|
103
|
+
`first!` raises LHC::NotFound if nothing was found.
|
104
|
+
|
105
|
+
## Batch processing
|
34
106
|
|
35
|
-
|
107
|
+
**Be carefull using methods for batch processing. They could result in a lot of HTTP requests!**
|
108
|
+
|
109
|
+
`all` fetches all records from the backend by doing multiple requests if necessary.
|
36
110
|
|
37
111
|
```ruby
|
38
|
-
|
39
|
-
|
40
|
-
|
112
|
+
data = Feedback.all
|
113
|
+
data.count # 998
|
114
|
+
data.total # 998
|
115
|
+
```
|
116
|
+
|
117
|
+
`find_each` is a more fine grained way to process single records that are fetched in batches.
|
41
118
|
|
42
|
-
|
43
|
-
|
44
|
-
|
119
|
+
```ruby
|
120
|
+
Feedback.find_each(start: 50, batch_size: 20, params: { has_reviews: true }) do |feedback|
|
121
|
+
# Iterates over each record. Starts with record nr. 50 and fetches 20 records each batch.
|
122
|
+
feedback
|
123
|
+
break if feedback.some_attribute == some_value
|
124
|
+
end
|
125
|
+
```
|
126
|
+
|
127
|
+
`find_in_batches` is used by `find_each` and processes batches.
|
128
|
+
```ruby
|
129
|
+
Feedback.find_in_batches(start: 50, batch_size: 20, params: { has_reviews: true }) do |feedbacks|
|
130
|
+
# Iterates over multiple records (batch size is 20). Starts with record nr. 50 and fetches 20 records each batch.
|
131
|
+
feedbacks
|
132
|
+
break if feedback.some_attribute == some_value
|
133
|
+
end
|
45
134
|
```
|
46
135
|
|
47
|
-
##
|
48
|
-
A collection contains multiple items.
|
136
|
+
## Create records
|
49
137
|
|
50
138
|
```ruby
|
51
|
-
|
52
|
-
|
53
|
-
|
139
|
+
feedback = Feedback.create(
|
140
|
+
recommended: true,
|
141
|
+
source_id: 'aaa',
|
142
|
+
content_ad_id: '1z-5r1fkaj'
|
143
|
+
)
|
144
|
+
```
|
145
|
+
|
146
|
+
When creation fails, the object contains errors. It provides them through the `errors` attribute:
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
feedback.errors #<LHS::Errors>
|
150
|
+
feedback.errors.include?(:ratings) # true
|
151
|
+
feedback.errors[:ratings] # ['REQUIRED_PROPERTY_VALUE']
|
152
|
+
record.errors.messages # {:ratings=>["REQUIRED_PROPERTY_VALUE"], :recommended=>["REQUIRED_PROPERTY_VALUE"]}
|
153
|
+
record.errors.message # ratings must be set when review or name or review_title is set | The property value is required; it cannot be null, empty, or blank."
|
154
|
+
```
|
155
|
+
|
156
|
+
## Build new records
|
157
|
+
|
158
|
+
Build and persist new items from scratch are done either with `new` or it's alias `build`.
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
feedback = Feedback.new(recommended: true)
|
162
|
+
feedback.save
|
163
|
+
```
|
164
|
+
|
165
|
+
## Include linked resources
|
166
|
+
|
167
|
+
When fetching records, you can specify in advance all the linked resources that you want to include in the results. With `includes`, LHS ensures that all matching and explicitly linked resources are loaded and merged.
|
168
|
+
|
169
|
+
The implementation is heavily influenced by [http://guides.rubyonrails.org/active_record_class_querying](http://guides.rubyonrails.org/active_record_class_querying.html#eager-loading-associations) and you should read it to understand this feature in all its glory.
|
170
|
+
|
171
|
+
### One-Level `includes`
|
172
|
+
|
173
|
+
```ruby
|
174
|
+
# a claim has a localch_account
|
175
|
+
claims = Claims.includes(:localch_account).where(place_id: 'huU90mB_6vAfUdVz_uDoyA')
|
176
|
+
claims.first.localch_account.email # 'test@email.com'
|
177
|
+
```
|
178
|
+
* [see the JSON without include](examples/claim_no_include.json)
|
179
|
+
* [see the JSON with include](examples/claim_with_include.json)
|
180
|
+
|
181
|
+
### Two-Level `includes`
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
# a feedback has a campaign, which has an entry
|
185
|
+
feedbacks = Feedback.includes(campaign: :entry).where(has_reviews: true)
|
186
|
+
feedbacks.first.campaign.entry.name # 'Casa Ferlin'
|
187
|
+
```
|
188
|
+
|
189
|
+
### Multiple `includes`
|
190
|
+
|
191
|
+
```ruby
|
192
|
+
# list of includes
|
193
|
+
claims = Claims.includes(:localch_account, :entry).where(place_id: 'huU90mB_6vAfUdVz_uDoyA')
|
194
|
+
|
195
|
+
# array of includes
|
196
|
+
claims = Claims.includes([:localch_account, :entry]).where(place_id: 'huU90mB_6vAfUdVz_uDoyA')
|
197
|
+
|
198
|
+
# Two-level with array of includes
|
199
|
+
feedbacks = Feedback.includes(campaign: [:entry, :user]).where(has_reviews: true)
|
200
|
+
```
|
201
|
+
|
202
|
+
### Known LHS::Records are used to request linked resources
|
203
|
+
|
204
|
+
When including linked resources with `includes`, known/defined services and endpoints are used to make those requests.
|
205
|
+
That also means that options for endpoints of linked resources are applied when requesting those in addition.
|
206
|
+
This allows you to include protected resources (e.g. OAuth) as endpoint options for oauth authentication get applied.
|
207
|
+
|
208
|
+
The [Auth Inteceptor](https://github.com/local-ch/lhc-core-interceptors#auth-interceptor) from [lhc-core-interceptors](https://github.com/local-ch/lhc-core-interceptors) is used to configure the following endpoints.
|
209
|
+
|
210
|
+
```ruby
|
211
|
+
class Favorite < LHS::Record
|
212
|
+
|
213
|
+
endpoint ':datastore/:user_id/favorites', auth: { bearer: -> { bearer_token } }
|
214
|
+
endpoint ':datastore/:user_id/favorites/:id', auth: { bearer: -> { bearer_token } }
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
class Place < LHS::Record
|
219
|
+
|
220
|
+
endpoint ':datastore/v2/places', auth: { bearer: -> { bearer_token } }
|
221
|
+
endpoint ':datastore/v2/places/:id', auth: { bearer: -> { bearer_token } }
|
222
|
+
|
223
|
+
end
|
224
|
+
|
225
|
+
Favorite.includes(:place).where(user_id: current_user.id)
|
226
|
+
# Will include places and applies endpoint options to authenticate the request.
|
227
|
+
```
|
228
|
+
|
229
|
+
## Map data
|
230
|
+
|
231
|
+
To influence how data is accessed/provied, you can use mappings to either map deep nested data or to manipulate data when its accessed. Simply create methods inside the LHS::Record. They can access underlying data:
|
232
|
+
|
233
|
+
```ruby
|
234
|
+
class LocalEntry < LHS::Record
|
235
|
+
endpoint ':datastore/v2/local-entries'
|
236
|
+
|
237
|
+
def name
|
238
|
+
addresses.first.business.identities.first.name
|
239
|
+
end
|
240
|
+
|
241
|
+
end
|
242
|
+
```
|
243
|
+
|
244
|
+
### Known LHS::Records when accessing mapped data from nested data
|
245
|
+
|
246
|
+
As LHS detects LHS::Records as soon as a link is present, mappings will also be applied on nested data:
|
247
|
+
|
248
|
+
```
|
249
|
+
class Place < LHS::Record
|
250
|
+
endpoint ':datastore/v2/places'
|
251
|
+
|
252
|
+
def name
|
253
|
+
addresses.first.business.identities.first.name
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
class Favorite < LHS::Record
|
258
|
+
endpoint ':datastore/v2/favorites'
|
259
|
+
end
|
260
|
+
|
261
|
+
favorite = Favorite.includes(:place).find(1)
|
262
|
+
favorite.place.name # local.ch AG
|
263
|
+
```
|
264
|
+
|
265
|
+
## Setters
|
266
|
+
|
267
|
+
You can change attributes of LHS::Records:
|
268
|
+
|
269
|
+
```
|
270
|
+
record = Feedback.find(id: 'z12f-3asm3ngals')
|
271
|
+
rcord.recommended = false
|
272
|
+
```
|
273
|
+
|
274
|
+
## Save
|
275
|
+
|
276
|
+
You can persist changes with `save`. `save` will return `false` if persisting fails. `save!` instead will raise an exception.
|
277
|
+
|
278
|
+
```ruby
|
279
|
+
feedback = Feedback.find('1z-5r1fkaj')
|
280
|
+
feedback.recommended = false
|
281
|
+
feedback.save
|
282
|
+
```
|
283
|
+
|
284
|
+
## Update
|
285
|
+
|
286
|
+
`update` will return false if persisting fails. `update!` instead will an raise exception.
|
287
|
+
|
288
|
+
`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.
|
289
|
+
|
290
|
+
```ruby
|
291
|
+
feedback = Feedback.find('1z-5r1fkaj')
|
292
|
+
feedback.update(recommended: false)
|
293
|
+
```
|
294
|
+
|
295
|
+
## Destroy
|
296
|
+
|
297
|
+
You can delete records remotely by calling `destroy` on an LHS::Record.
|
298
|
+
|
299
|
+
```ruby
|
300
|
+
feedback = Feedback.find('1z-5r1fkaj')
|
301
|
+
feedback.destroy
|
302
|
+
```
|
303
|
+
|
304
|
+
## Validation
|
305
|
+
|
306
|
+
In order to validate LHS::Records before persisting them, you can use the `valid?` (`validate` alias) method.
|
307
|
+
|
308
|
+
The specific endpoint has to support validations with the `persist=false` parameter. The endpoint has to be enabled (opt-in) for validations in the service configuration.
|
309
|
+
|
310
|
+
```
|
311
|
+
class User < LHS::Record
|
312
|
+
endpoint ':datastore/v2/users', validates: true
|
313
|
+
end
|
314
|
+
|
315
|
+
user = User.build(email: 'im not an email address')
|
316
|
+
unless user.valid?
|
317
|
+
fail(user.errors[:email])
|
318
|
+
end
|
54
319
|
```
|
55
320
|
|
56
|
-
|
321
|
+
## Collections: Offset / Limit / Pagination
|
57
322
|
|
58
|
-
|
59
|
-
An item is a concrete record. It can be part of another proxy like collection.
|
323
|
+
You can paginate by passing offset, and limit params. They will be forwarded to the backend.
|
60
324
|
|
61
325
|
```ruby
|
62
|
-
data = Feedback.where(
|
63
|
-
data.
|
64
|
-
|
326
|
+
data = Feedback.where(limit: 50)
|
327
|
+
data.count // 50
|
328
|
+
Feedback.where(limit: 50, offset: 51)
|
65
329
|
```
|
66
330
|
|
67
|
-
|
331
|
+
`total` provides total amount of items (even if paginated).
|
332
|
+
`limit` provides amount of items per page.
|
333
|
+
`offset` provides how many items where skipped to start the current page.
|
data/lhs.gemspec
CHANGED
@@ -7,11 +7,11 @@ require "lhs/version"
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "lhs"
|
9
9
|
s.version = LHS::VERSION
|
10
|
-
s.authors = ['local
|
10
|
+
s.authors = ['https://github.com/local-ch/lhs/graphs/contributors']
|
11
11
|
s.email = ['ws-operations@local.ch']
|
12
12
|
s.homepage = 'https://github.com/local-ch/lhs'
|
13
|
-
s.summary = '
|
14
|
-
s.description =
|
13
|
+
s.summary = 'Rails gem providing an easy, active-record-like interface to use http backend services'
|
14
|
+
s.description = s.summary
|
15
15
|
|
16
16
|
s.files = `git ls-files`.split("\n")
|
17
17
|
s.test_files = `git ls-files -- spec/*`.split("\n")
|
data/lib/lhs.rb
CHANGED
@@ -4,10 +4,3 @@ module LHS
|
|
4
4
|
end
|
5
5
|
|
6
6
|
Gem.find_files('lhs/**/*.rb').each { |path| require path }
|
7
|
-
|
8
|
-
# Preload all the services that are defined in app/services
|
9
|
-
class Engine < Rails::Engine
|
10
|
-
initializer 'Load all services' do |app|
|
11
|
-
Dir.glob(app.root.join('app/services/**/*.rb')).each {|file| require file }
|
12
|
-
end
|
13
|
-
end
|
data/lib/lhs/collection.rb
CHANGED
@@ -25,7 +25,7 @@ class LHS::Collection < LHS::Proxy
|
|
25
25
|
def _collection
|
26
26
|
raw = _data._raw if _data._raw.is_a?(Array)
|
27
27
|
raw ||= _data._raw[:items]
|
28
|
-
Collection.new(raw, _data, _data.
|
28
|
+
Collection.new(raw, _data, _data._record_class)
|
29
29
|
end
|
30
30
|
|
31
31
|
def _raw
|
@@ -59,16 +59,16 @@ class LHS::Collection < LHS::Proxy
|
|
59
59
|
attr_accessor :raw
|
60
60
|
delegate :last, :sample, :[], :present?, :blank?, :empty?, to: :raw
|
61
61
|
|
62
|
-
def initialize(raw, parent,
|
62
|
+
def initialize(raw, parent, record)
|
63
63
|
self.raw = raw
|
64
64
|
@parent = parent
|
65
|
-
@
|
65
|
+
@record = record
|
66
66
|
end
|
67
67
|
|
68
68
|
def each(&block)
|
69
69
|
raw.each do |item|
|
70
70
|
if item.is_a? Hash
|
71
|
-
yield LHS::Data.new(item, @parent, @
|
71
|
+
yield LHS::Data.new(item, @parent, @record)
|
72
72
|
else
|
73
73
|
yield item
|
74
74
|
end
|
@@ -7,8 +7,8 @@ class LHS::Item < LHS::Proxy
|
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
|
9
9
|
def destroy
|
10
|
-
|
11
|
-
_data._request =
|
10
|
+
record = _data._root._record_class
|
11
|
+
_data._request = record.request(method: :delete, url: href)._request
|
12
12
|
_data
|
13
13
|
end
|
14
14
|
end
|
@@ -14,14 +14,14 @@ class LHS::Item < LHS::Proxy
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def save!
|
17
|
-
|
17
|
+
record = _data._root._record_class
|
18
18
|
data = _data._raw.dup
|
19
19
|
url = if href.present?
|
20
20
|
href
|
21
21
|
else
|
22
|
-
|
22
|
+
record.find_endpoint(data).compile(data)
|
23
23
|
end
|
24
|
-
data =
|
24
|
+
data = record.request(method: :post, url: url, body: data.to_json, headers: {'Content-Type' => 'application/json'})
|
25
25
|
self._data.merge_raw!(data)
|
26
26
|
true
|
27
27
|
end
|