bodhi-slam 0.8.6 → 0.8.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/bodhi-slam.rb +3 -3
- data/lib/bodhi-slam/factory.rb +80 -20
- data/lib/bodhi-slam/properties.rb +127 -81
- data/lib/bodhi-slam/resource.rb +296 -140
- data/lib/bodhi-slam/simulator.rb +1 -5
- data/lib/bodhi-slam/support.rb +13 -3
- data/lib/bodhi-slam/types.rb +139 -15
- data/lib/bodhi-slam/validations.rb +74 -78
- metadata +16 -2
data/lib/bodhi-slam/resource.rb
CHANGED
@@ -1,16 +1,33 @@
|
|
1
1
|
module Bodhi
|
2
|
+
# Interface for interacting with resources on the HotSchedules IoT Platform.
|
2
3
|
module Resource
|
4
|
+
# @!parse extend Bodhi::Resource::ClassMethods
|
3
5
|
|
6
|
+
# The API context that binds a +Bodhi::Resource+ instance to the HotSchedules IoT Platform
|
7
|
+
# @note This is required for the all instance methods to work correctly
|
8
|
+
# @return [Bodhi::Context] the API context linked to this object
|
4
9
|
attr_accessor :bodhi_context
|
5
10
|
|
6
11
|
module ClassMethods
|
7
12
|
|
8
|
-
|
13
|
+
# Sets the resources embedded status to either true/false.
|
14
|
+
#
|
15
|
+
# @param status [Boolean]
|
16
|
+
# @return [Boolean]
|
17
|
+
def embedded(status); @embedded = status; end
|
18
|
+
|
19
|
+
# Checks if the resource is embedded
|
20
|
+
#
|
21
|
+
# @return [Boolean]
|
9
22
|
def is_embedded?; @embedded; end
|
10
23
|
|
11
24
|
# Defines the given +name+ and +options+ as a form attribute for the class.
|
12
|
-
# The +name+ is set as a property, and validations & factory generators
|
13
|
-
#
|
25
|
+
# The +name+ is set as a property, and validations & factory generators
|
26
|
+
# are added based on the supplied +options+
|
27
|
+
#
|
28
|
+
# @param name [String]
|
29
|
+
# @param options [Hash]
|
30
|
+
# @example
|
14
31
|
# class User
|
15
32
|
# include Bodhi::Resource
|
16
33
|
#
|
@@ -27,13 +44,30 @@ module Bodhi
|
|
27
44
|
generates(name.to_sym, options)
|
28
45
|
end
|
29
46
|
|
47
|
+
# Generates a new {Bodhi::Type} instance using the classes metadata
|
48
|
+
#
|
49
|
+
# @return [Bodhi::Type]
|
50
|
+
# @example
|
51
|
+
# class User
|
52
|
+
# include Bodhi::Resource
|
53
|
+
#
|
54
|
+
# field :first_name, type: "String", required: true, is_not_blank: true
|
55
|
+
# field :last_name, type: "String", required: true, is_not_blank: true
|
56
|
+
# field :email, type: "String", required: true, is_not_blank: true, is_email: true
|
57
|
+
#
|
58
|
+
# index ["last_name"]
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
# User.build_type #=> #<Bodhi::Type:0x007fbff403e808 @name="User" @properties={...} @indexes=[...]>
|
30
62
|
def build_type
|
31
63
|
Bodhi::Type.new(name: self.name, properties: self.properties, indexes: self.indexes, embedded: self.is_embedded?)
|
32
64
|
end
|
33
65
|
|
34
66
|
# Saves a batch of resources to the Bodhi Cloud in the given +context+
|
35
67
|
# Returns an array of JSON objects describing the results for each record in the batch
|
36
|
-
#
|
68
|
+
#
|
69
|
+
# @deprecated This uses the old bulk upload process and will be removed in version 1.0.0 DO NOT USE!
|
70
|
+
# @example
|
37
71
|
# context = Bodhi::Context.new
|
38
72
|
# list = Resource.factory.build_list(10)
|
39
73
|
# Resource.save_batch(context, list)
|
@@ -43,43 +77,80 @@ module Bodhi
|
|
43
77
|
batch
|
44
78
|
end
|
45
79
|
|
46
|
-
# Counts all records that match the given query
|
80
|
+
# Counts all records that match the given +query+
|
47
81
|
#
|
48
|
-
#
|
49
|
-
#
|
82
|
+
# Equivalent CURL command:
|
83
|
+
# curl -u {username}:{password} https://{server}/{namespace}/resources/{resource}/count?where={query}
|
84
|
+
# @param context [Bodhi::Context]
|
85
|
+
# @param query [Hash] MongoDB query operations
|
86
|
+
# @example
|
87
|
+
# Resource.count(context) #=> # count all records
|
88
|
+
# Resource.count(context, name: "Foo") #=> # count all records with name == "Foo"
|
50
89
|
def count(context, query={})
|
51
90
|
query_obj = Bodhi::Query.new(name)
|
52
91
|
query_obj.where(query).from(context)
|
53
92
|
query_obj.count
|
54
93
|
end
|
55
94
|
|
56
|
-
# Deletes all records that match the given query
|
95
|
+
# Deletes all records that match the given +query+
|
57
96
|
#
|
58
|
-
#
|
59
|
-
#
|
97
|
+
# Equivalent CURL command:
|
98
|
+
# curl -u {username}:{password} -X DELETE https://{server}/{namespace}/resources/{resource}?where={query}
|
99
|
+
# @note Beware: It's easy to delete an entire collection with this method! Use it wisely :)
|
100
|
+
# @param context [Bodhi::Context]
|
101
|
+
# @param query [Hash] MongoDB query operations
|
102
|
+
# @return [Hash] with key: +count+
|
103
|
+
# @todo add more query complex examples
|
104
|
+
# @example
|
105
|
+
# # delete with a query
|
106
|
+
# Resource.delete!(context, sys_created_at: { '$lte': 6.months.ago.iso8601 })
|
107
|
+
#
|
108
|
+
# # delete all records
|
109
|
+
# Resource.delete!(context)
|
60
110
|
def delete!(context, query={})
|
61
111
|
query_obj = Bodhi::Query.new(name)
|
62
112
|
query_obj.where(query).from(context)
|
63
113
|
query_obj.delete
|
64
114
|
end
|
65
115
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
116
|
+
# Creates a new resource with the given +properties+
|
117
|
+
# and POSTs it to the IoT Platform
|
118
|
+
#
|
119
|
+
# Equivalent CURL command:
|
120
|
+
# curl -u {username}:{password} -X POST -H "Content-Type: application/json" \
|
121
|
+
# https://{server}/{namespace}/resources/{resource} \
|
122
|
+
# -d '{properties}'
|
123
|
+
# @param context [Bodhi::Context]
|
124
|
+
# @param properties [Hash]
|
125
|
+
# @return [Bodhi::Resource]
|
126
|
+
# @raise [Bodhi::ContextErrors] if the given +Bodhi::Context+ is invalid
|
127
|
+
# @raise [Bodhi::ApiErrors] if the record cannot be saved
|
128
|
+
# Resource.create!(context, name: "Foo", age: 125, tags: ["green", "blue"])
|
129
|
+
def create!(context, properties)
|
71
130
|
if context.invalid?
|
72
131
|
raise Bodhi::ContextErrors.new(context.errors.messages), context.errors.to_a.to_s
|
73
132
|
end
|
74
133
|
|
75
|
-
record
|
134
|
+
# Build a new record and set the context
|
135
|
+
record = self.new(properties)
|
76
136
|
record.bodhi_context = context
|
137
|
+
|
138
|
+
# POST to the IoT Platform
|
77
139
|
record.save!
|
78
140
|
return record
|
79
141
|
end
|
80
142
|
|
81
|
-
#
|
82
|
-
#
|
143
|
+
# Search for a record with the given +id+
|
144
|
+
#
|
145
|
+
# Equivalent CURL command:
|
146
|
+
# curl -u {username}:{password} https://{server}/{namespace}/resources/{resource}/{id}
|
147
|
+
# @param id [String] the {Bodhi::Properties#sys_id} of the record
|
148
|
+
# @param context [Bodhi::Context]
|
149
|
+
# @return [Bodhi::Resource]
|
150
|
+
# @raise [Bodhi::ContextErrors] if the given +Bodhi::Context+ is invalid
|
151
|
+
# @raise [Bodhi::ApiErrors] if response status is NOT +200+
|
152
|
+
# @raise [ArgumentError] if the given +id+ is NOT a +String+
|
153
|
+
# @example
|
83
154
|
# context = Bodhi::Context.new
|
84
155
|
# id = Resource.factory.create(context).sys_id
|
85
156
|
# obj = Resource.find(context, id)
|
@@ -110,9 +181,16 @@ module Bodhi
|
|
110
181
|
record
|
111
182
|
end
|
112
183
|
|
113
|
-
# Returns all records
|
114
|
-
#
|
115
|
-
#
|
184
|
+
# Returns all records in the given +context+
|
185
|
+
#
|
186
|
+
# All records returned by this method will have their
|
187
|
+
# {#bodhi_context} attribute set to +context+
|
188
|
+
# @note This method will return ALL records!! Don't use on large collections! YE BE WARNED!!
|
189
|
+
# @param context [Bodhi::Context]
|
190
|
+
# @return [Array<Bodhi::Resource>]
|
191
|
+
# @raise [Bodhi::ContextErrors] if the given +context+ is invalid
|
192
|
+
# @raise [Bodhi::ApiErrors] if any response status is NOT 200
|
193
|
+
# @example
|
116
194
|
# Resource.find_all(context) # => [#<Resource:0x007fbff403e808>, #<Resource:0x007fbff403e808>, ...]
|
117
195
|
def find_all(context=nil)
|
118
196
|
if context.nil?
|
@@ -144,10 +222,19 @@ module Bodhi
|
|
144
222
|
end
|
145
223
|
alias :all :find_all
|
146
224
|
|
147
|
-
#
|
148
|
-
#
|
149
|
-
#
|
150
|
-
#
|
225
|
+
# Performs MongoDB aggregations using the given +pipeline+
|
226
|
+
#
|
227
|
+
# Equivalent CURL command:
|
228
|
+
# curl -u {username}:{password} https://{server}/{namespace}/resources/{resource}/aggregate?pipeline={pipeline}
|
229
|
+
# @note Large aggregations can be very time and resource intensive!
|
230
|
+
# @param context [Bodhi::Context]
|
231
|
+
# @param pipeline [String]
|
232
|
+
# @return [Hash] the JSON response converted to a Ruby Hash
|
233
|
+
# @raise [ArgumentError] if the given +pipeline+ is NOT a +String+
|
234
|
+
# @raise [Bodhi::ContextErrors] if the given +context+ is invalid
|
235
|
+
# @raise [Bodhi::ApiErrors] if any response status is NOT +200+
|
236
|
+
# @example
|
237
|
+
# Resource.aggregate(context, "[{ $match: { age: { $gte: 21 }}}]")
|
151
238
|
def aggregate(context, pipeline)
|
152
239
|
if context.invalid?
|
153
240
|
raise Bodhi::ContextErrors.new(context.errors.messages), context.errors.to_a.to_s
|
@@ -169,11 +256,14 @@ module Bodhi
|
|
169
256
|
result.body
|
170
257
|
end
|
171
258
|
|
172
|
-
# Returns a Bodhi::Query object
|
173
|
-
#
|
259
|
+
# Returns a {Bodhi::Query} object with the given +query+
|
260
|
+
#
|
261
|
+
# @param query [Hash] the MongoDB query operations
|
262
|
+
# @return [Bodhi::Query<Bodhi::Resource>] a {Bodhi::Query} object, bound to the {Bodhi::Resource} with the given +query+
|
263
|
+
# @example
|
174
264
|
# context = Bodhi::Context.new
|
175
|
-
# Resource.where(
|
176
|
-
# Resource.where(
|
265
|
+
# Resource.where({conditions}).from(context).all
|
266
|
+
# Resource.where({conditions}).and({more conditions}).limit(10).from(context).all
|
177
267
|
def where(query)
|
178
268
|
query_obj = Bodhi::Query.new(name)
|
179
269
|
query_obj.where(query)
|
@@ -181,145 +271,211 @@ module Bodhi
|
|
181
271
|
end
|
182
272
|
end
|
183
273
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
274
|
+
# POST the record to the IoT Platform. Returns +true+ if record was saved correctly.
|
275
|
+
#
|
276
|
+
# Equivalent CURL command:
|
277
|
+
# curl -u {username}:{password} -X POST -H "Content-Type: application/json" \
|
278
|
+
# https://{server}/{namespace}/resources/{resource} \
|
279
|
+
# -d '{properties}'
|
280
|
+
# @return [Boolean]
|
281
|
+
# @raise [Bodhi::ContextErrors] if the given +Bodhi::Context+ is invalid
|
282
|
+
# @example
|
283
|
+
# obj = Resource.new
|
284
|
+
# obj.save # => true
|
285
|
+
# obj.persisted? # => true
|
286
|
+
def save
|
287
|
+
if invalid?
|
288
|
+
return false
|
289
|
+
end
|
198
290
|
|
199
|
-
|
200
|
-
|
201
|
-
|
291
|
+
if bodhi_context.nil?
|
292
|
+
@bodhi_context = Bodhi::Context.global_context
|
293
|
+
end
|
202
294
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
request.headers[bodhi_context.credentials_header] = bodhi_context.credentials
|
207
|
-
request.body = attributes.to_json
|
208
|
-
end
|
209
|
-
|
210
|
-
if result.status != 201
|
211
|
-
raise Bodhi::ApiErrors.new(body: result.body, status: result.status), "status: #{result.status}, body: #{result.body}"
|
212
|
-
end
|
295
|
+
if bodhi_context.invalid?
|
296
|
+
raise Bodhi::ContextErrors.new(bodhi_context.errors.messages), bodhi_context.errors.to_a.to_s
|
297
|
+
end
|
213
298
|
|
214
|
-
|
215
|
-
|
216
|
-
|
299
|
+
result = bodhi_context.connection.post do |request|
|
300
|
+
request.url "/#{bodhi_context.namespace}/resources/#{self.class}"
|
301
|
+
request.headers['Content-Type'] = 'application/json'
|
302
|
+
request.headers[bodhi_context.credentials_header] = bodhi_context.credentials
|
303
|
+
request.body = attributes.to_json
|
304
|
+
end
|
217
305
|
|
218
|
-
|
306
|
+
if result.headers['location']
|
307
|
+
@sys_id = result.headers['location'].match(/(?<id>[a-zA-Z0-9]{24})/)[:id]
|
219
308
|
end
|
220
309
|
|
221
|
-
|
222
|
-
|
223
|
-
# obj = Resouce.new
|
224
|
-
# obj.save!
|
225
|
-
# obj.persisted? # => true
|
226
|
-
def save!
|
227
|
-
if bodhi_context.invalid?
|
228
|
-
raise Bodhi::ContextErrors.new(bodhi_context.errors.messages), bodhi_context.errors.to_a.to_s
|
229
|
-
end
|
310
|
+
true
|
311
|
+
end
|
230
312
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
313
|
+
# POST the record to the IoT Platform. Raises error if record could not be saved
|
314
|
+
#
|
315
|
+
# Equivalent CURL command:
|
316
|
+
# curl -u {username}:{password} -X POST -H "Content-Type: application/json" \
|
317
|
+
# https://{server}/{namespace}/resources/{resource} \
|
318
|
+
# -d '{properties}'
|
319
|
+
# @return [nil]
|
320
|
+
# @raise [Bodhi::ContextErrors] if the given +Bodhi::Context+ is invalid
|
321
|
+
# @raise [Bodhi::ApiErrors] if the response status is NOT +201+
|
322
|
+
# @example
|
323
|
+
# obj = Resource.new
|
324
|
+
# obj.save # => true
|
325
|
+
# obj.persisted? # => true
|
326
|
+
def save!
|
327
|
+
if bodhi_context.invalid?
|
328
|
+
raise Bodhi::ContextErrors.new(bodhi_context.errors.messages), bodhi_context.errors.to_a.to_s
|
329
|
+
end
|
241
330
|
|
242
|
-
|
243
|
-
|
244
|
-
|
331
|
+
result = bodhi_context.connection.post do |request|
|
332
|
+
request.url "/#{bodhi_context.namespace}/resources/#{self.class}"
|
333
|
+
request.headers['Content-Type'] = 'application/json'
|
334
|
+
request.headers[bodhi_context.credentials_header] = bodhi_context.credentials
|
335
|
+
request.body = attributes.to_json
|
245
336
|
end
|
246
337
|
|
247
|
-
|
248
|
-
result
|
249
|
-
request.url "/#{bodhi_context.namespace}/resources/#{self.class}/#{sys_id}"
|
250
|
-
request.headers[bodhi_context.credentials_header] = bodhi_context.credentials
|
251
|
-
end
|
252
|
-
|
253
|
-
if result.status != 204
|
254
|
-
raise Bodhi::ApiErrors.new(body: result.body, status: result.status), "status: #{result.status}, body: #{result.body}"
|
255
|
-
end
|
338
|
+
if result.status != 201
|
339
|
+
raise Bodhi::ApiErrors.new(body: result.body, status: result.status), "status: #{result.status}, body: #{result.body}"
|
256
340
|
end
|
257
|
-
alias :destroy :delete!
|
258
341
|
|
259
|
-
|
260
|
-
|
342
|
+
if result.headers['location']
|
343
|
+
@sys_id = result.headers['location'].match(/(?<id>[a-zA-Z0-9]{24})/)[:id]
|
344
|
+
end
|
261
345
|
|
262
|
-
|
263
|
-
|
264
|
-
end
|
346
|
+
return nil
|
347
|
+
end
|
265
348
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
349
|
+
# DELETE the record from the IoT Platform. Raises error if record could not be deleted
|
350
|
+
#
|
351
|
+
# Equivalent CURL command:
|
352
|
+
# curl -u {username}:{password} -X DELETE https://{server}/{namespace}/resources/{resource}/{sys_id}
|
353
|
+
# @return [nil]
|
354
|
+
# @raise [Bodhi::ContextErrors] if the given +Bodhi::Context+ is invalid
|
355
|
+
# @raise [Bodhi::ApiErrors] if the response status is NOT +204+
|
356
|
+
# @example
|
357
|
+
# #given: obj.persisted? # => true
|
358
|
+
# obj.delete! # => nil
|
359
|
+
def delete!
|
360
|
+
result = bodhi_context.connection.delete do |request|
|
361
|
+
request.url "/#{bodhi_context.namespace}/resources/#{self.class}/#{sys_id}"
|
362
|
+
request.headers[bodhi_context.credentials_header] = bodhi_context.credentials
|
363
|
+
end
|
272
364
|
|
273
|
-
|
274
|
-
|
275
|
-
|
365
|
+
if result.status != 204
|
366
|
+
raise Bodhi::ApiErrors.new(body: result.body, status: result.status), "status: #{result.status}, body: #{result.body}"
|
367
|
+
end
|
276
368
|
|
277
|
-
|
369
|
+
return nil
|
370
|
+
end
|
371
|
+
alias :destroy :delete!
|
372
|
+
|
373
|
+
# PUT an updated version of the record to the IoT Platform. Raises error if record could not be updated
|
374
|
+
#
|
375
|
+
# Equivalent CURL command:
|
376
|
+
# curl -u {username}:{password} -X PUT -H "Content-Type: application/json" \
|
377
|
+
# https://{server}/{namespace}/resources/{resource}/{sys_id} \
|
378
|
+
# -d '{updated properties}'
|
379
|
+
# @param properties [Hash] Key/Value pairs of the properties to update
|
380
|
+
# @return [nil]
|
381
|
+
# @raise [Bodhi::ContextErrors] if the given +Bodhi::Context+ is invalid
|
382
|
+
# @raise [Bodhi::ApiErrors] if the response status is NOT +204+
|
383
|
+
# @example
|
384
|
+
# #given: obj.persisted? # => true
|
385
|
+
# obj.update!(foo: "test", bar: 12345) # => nil
|
386
|
+
def update!(properties)
|
387
|
+
update_attributes(properties)
|
388
|
+
|
389
|
+
if invalid?
|
390
|
+
return false
|
278
391
|
end
|
279
|
-
alias :update :update!
|
280
392
|
|
281
|
-
|
282
|
-
|
393
|
+
result = bodhi_context.connection.put do |request|
|
394
|
+
request.url "/#{bodhi_context.namespace}/resources/#{self.class}/#{sys_id}"
|
395
|
+
request.headers['Content-Type'] = 'application/json'
|
396
|
+
request.headers[bodhi_context.credentials_header] = bodhi_context.credentials
|
397
|
+
request.body = attributes.to_json
|
398
|
+
end
|
283
399
|
|
284
|
-
|
285
|
-
|
286
|
-
|
400
|
+
if result.status != 204
|
401
|
+
raise Bodhi::ApiErrors.new(body: result.body, status: result.status), "status: #{result.status}, body: #{result.body}"
|
402
|
+
end
|
287
403
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
404
|
+
true
|
405
|
+
end
|
406
|
+
alias :update :update!
|
407
|
+
|
408
|
+
|
409
|
+
# Create or Update an existing record on the IoT Platform. Raises error if record could not be updated
|
410
|
+
#
|
411
|
+
# Equivalent CURL command:
|
412
|
+
# curl -u {username}:{password} -X PUT -H "Content-Type: application/json" \
|
413
|
+
# https://{server}/{namespace}/resources/{resource}/{sys_id} \
|
414
|
+
# -d '{updated properties}'
|
415
|
+
# @param properties [Hash] Key/Value pairs of the properties to update
|
416
|
+
# @return [nil]
|
417
|
+
# @raise [Bodhi::ContextErrors] if the given +Bodhi::Context+ is invalid
|
418
|
+
# @raise [Bodhi::ApiErrors] if the response status is NOT +204+ OR +201+
|
419
|
+
# @example
|
420
|
+
# #given: obj.persisted? # => true
|
421
|
+
# obj.upsert!(foo: "test", bar: 12345) # => nil
|
422
|
+
def upsert!(properties={})
|
423
|
+
update_attributes(properties)
|
424
|
+
|
425
|
+
if invalid?
|
426
|
+
return false
|
427
|
+
end
|
294
428
|
|
295
|
-
|
296
|
-
|
297
|
-
|
429
|
+
result = bodhi_context.connection.put do |request|
|
430
|
+
request.url "/#{bodhi_context.namespace}/resources/#{self.class}?upsert=true"
|
431
|
+
request.headers['Content-Type'] = 'application/json'
|
432
|
+
request.headers[bodhi_context.credentials_header] = bodhi_context.credentials
|
433
|
+
request.body = attributes.to_json
|
434
|
+
end
|
298
435
|
|
299
|
-
|
300
|
-
|
301
|
-
end
|
436
|
+
unless [204, 201].include?(result.status)
|
437
|
+
raise Bodhi::ApiErrors.new(body: result.body, status: result.status), "status: #{result.status}, body: #{result.body}"
|
302
438
|
end
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
439
|
+
|
440
|
+
if result.headers['location']
|
441
|
+
@sys_id = result.headers['location'].match(/(?<id>[a-zA-Z0-9]{24})/)[:id]
|
442
|
+
end
|
443
|
+
end
|
444
|
+
alias :upsert :upsert!
|
445
|
+
|
446
|
+
|
447
|
+
# PATCH an existing record on the IoT Platform. Raises error if record could not be updated
|
448
|
+
#
|
449
|
+
# Equivalent CURL command:
|
450
|
+
# curl -u {username}:{password} -X PATCH -H "Content-Type: application/json" \
|
451
|
+
# https://{server}/{namespace}/resources/{resource}/{sys_id} \
|
452
|
+
# -d '[{operation1}, {operation2}, ...]'
|
453
|
+
#
|
454
|
+
# @note This method will not update the object after patching. Only the record on the IoT Platform will be updated.
|
455
|
+
# @param operations [Array<Hash>] Array of PATCH operations
|
456
|
+
# @return [nil]
|
457
|
+
# @raise [Bodhi::ContextErrors] if the given +Bodhi::Context+ is invalid
|
458
|
+
# @raise [Bodhi::ApiErrors] if the response status is NOT +204+ OR +201+
|
459
|
+
# @example
|
460
|
+
# #given: obj.persisted? # => true
|
461
|
+
# obj.upsert!(foo: "test", bar: 12345) # => nil
|
462
|
+
def patch!(operations)
|
463
|
+
result = bodhi_context.connection.patch do |request|
|
464
|
+
request.url "/#{bodhi_context.namespace}/resources/#{self.class}/#{sys_id}"
|
465
|
+
request.headers['Content-Type'] = 'application/json'
|
466
|
+
request.headers[bodhi_context.credentials_header] = bodhi_context.credentials
|
467
|
+
request.body = operations.to_json
|
468
|
+
end
|
469
|
+
|
470
|
+
if result.status != 204
|
471
|
+
raise Bodhi::ApiErrors.new(body: result.body, status: result.status), "status: #{result.status}, body: #{result.body}"
|
316
472
|
end
|
317
473
|
end
|
318
474
|
|
319
475
|
def self.included(base)
|
320
476
|
base.extend(ClassMethods)
|
321
|
-
base.include(
|
477
|
+
base.include(Bodhi::Properties, Bodhi::Associations, Bodhi::Validations, Bodhi::Indexes, Bodhi::Factories)
|
322
478
|
base.instance_variable_set(:@embedded, false)
|
323
479
|
end
|
324
480
|
end
|
325
|
-
end
|
481
|
+
end
|