built.io 0.7 → 0.8

Sign up to get free protection for your applications and to get access to all the features.
data/lib/built/object.rb CHANGED
@@ -25,7 +25,7 @@ module Built
25
25
 
26
26
  instantiate(
27
27
  Built.client.request(uri)
28
- .parsed_response["object"]
28
+ .json["object"]
29
29
  )
30
30
 
31
31
  self
@@ -35,27 +35,34 @@ module Built
35
35
  # @param [Hash] options Options
36
36
  # @option options [Boolean] :timeless Perform a timeless update
37
37
  # @option options [Boolean] :draft Save the object as draft
38
+ # @option options [Boolean] :include_owner Include the owner of the object in the response
39
+ # @option options [Boolean] :include Include a reference field in the response
38
40
  # @raise BuiltAPIError
39
41
  # @return [Object] self
40
42
  def save(options={})
43
+ headers = {}
44
+ query = {}
45
+ unpublish if options[:draft]
46
+ query[:include_owner] = true if options[:include_owner]
47
+ query[:include] = options[:include] if options[:include]
48
+
41
49
  if is_new?
42
50
  # create
43
51
  instantiate(
44
- Built.client.request(uri, :post, wrap)
45
- .parsed_response["object"]
52
+ Built.client.request(uri, :post, wrap, nil, headers)
53
+ .json["object"]
46
54
  )
47
55
  else
48
- headers = {}
49
-
50
56
  headers[:timeless] = true if options[:timeless]
51
- self["published"] = false if options[:draft]
52
57
 
53
58
  # update
54
59
  instantiate(
55
60
  Built.client.request(uri, :put, wrap, nil, headers)
56
- .parsed_response["object"]
61
+ .json["object"]
57
62
  )
58
63
  end
64
+
65
+ self
59
66
  end
60
67
 
61
68
  # Delete this object
@@ -80,27 +87,294 @@ module Built
80
87
  Built::Class.get(@class_uid)
81
88
  end
82
89
 
90
+ # Assign references based on a condition
91
+ # Searches for objects in the referred class and adds them as references
92
+ # @param [String] path The reference field
93
+ # @param [Query] query The query to apply when searching
94
+ # @return [Object] self
95
+ def set_reference_where(path, query)
96
+ Util.type_check("path", path, String)
97
+ Util.type_check("query", query, Query)
98
+
99
+ self[path] = {
100
+ "WHERE" => query.params["query"]
101
+ }
102
+
103
+ self
104
+ end
105
+
106
+ # Set reference for a field
107
+ # The reference parameter can be an existing uid, an existing object,
108
+ # or a new object. New objects will be created inline before being assigned
109
+ # as references.
110
+ # @param [String] path The path of the reference
111
+ # @param [String, Object, Array<String>, Array<Object>] value The value to assign
112
+ def set_reference(path, value)
113
+ Util.type_check("path", path, String)
114
+ value = value.is_a?(Array) ? value : [value]
115
+
116
+ self[path] = value.map do |val|
117
+ case val.class
118
+ when String
119
+ val
120
+ when Built::Object
121
+ val.is_new? ? val : val.uid
122
+ else
123
+ nil
124
+ end
125
+ end.compact!
126
+
127
+ self
128
+ end
129
+
130
+ # Decrement the value of a number field by the given number
131
+ # @param [String] path The number field
132
+ # @param [Fixnum] number The number to decrement
133
+ # @return [Object] self
134
+ def decrement(path, number=nil)
135
+ Util.type_check("path", path, String)
136
+ Util.type_check("number", number, Fixnum) if number
137
+
138
+ self[path] = {
139
+ "SUB" => number || 1
140
+ }
141
+
142
+ self
143
+ end
144
+
145
+ # Increment the value of a number field by the given number
146
+ # @param [String] path The number field
147
+ # @param [Fixnum] number The number to increment
148
+ # @return [Object] self
149
+ def increment(path, number=nil)
150
+ Util.type_check("path", path, String)
151
+ Util.type_check("number", number, Fixnum) if number
152
+
153
+ self[path] = {
154
+ "ADD" => number || 1
155
+ }
156
+
157
+ self
158
+ end
159
+
160
+ # Multiply the value of a number field by the given number
161
+ # @param [String] path The number field
162
+ # @param [Fixnum] number The number to multiply with
163
+ # @return [Object] self
164
+ def multiply(path, number)
165
+ Util.type_check("path", path, String)
166
+ Util.type_check("number", number, Fixnum)
167
+
168
+ self[path] = {
169
+ "MUL" => number
170
+ }
171
+
172
+ self
173
+ end
174
+
175
+ # Divide the value of a number field by the given number
176
+ # @param [String] path The number field
177
+ # @param [Fixnum] number The number to divide with
178
+ # @return [Object] selfs
179
+ def divide(path, number)
180
+ Util.type_check("path", path, String)
181
+ Util.type_check("number", number, Fixnum)
182
+
183
+ self[path] = {
184
+ "DIV" => number
185
+ }
186
+
187
+ self
188
+ end
189
+
190
+ # Update value at the given index for a multiple field
191
+ # @param [String] path The field name on which the operation is to be applied
192
+ # @param [#read] value Update the field with this value
193
+ # @param [Fixnum] index
194
+ # @return [Object] self
195
+ def update_value(path, value, index)
196
+ # TODO: convert these into operations that are transparently executed on save
197
+ # The user should be able to access the values transparently.
198
+ Util.type_check("path", path, String)
199
+ Util.type_check("index", index, Fixnum)
200
+
201
+ self[path] = {
202
+ "UPDATE" => {
203
+ "data" => value,
204
+ "index" => index
205
+ }
206
+ }
207
+
208
+ self
209
+ end
210
+
211
+ # Pull value from a multiple field
212
+ # @param [String] path The field name on which the operation is to be applied
213
+ # @param [#read] value Pull a certain value from the field
214
+ # @param [Fixnum] index Pull a certain index from the field
215
+ # @return [Object] self
216
+ def pull_value(path, value=nil, index=nil)
217
+ Util.type_check("path", path, String)
218
+ Util.type_check("index", index, Fixnum) if index
219
+
220
+ if value
221
+ value = value.is_a?(Array) ? value : [value]
222
+
223
+ self[path] = {
224
+ "PULL" => {
225
+ "data" => value
226
+ }
227
+ }
228
+ elsif index
229
+ self[path] = {
230
+ "PULL" => {
231
+ "index" => index
232
+ }
233
+ }
234
+ else
235
+ raise BuiltError, I18n.t("objects.pull_require")
236
+ end
237
+
238
+ self
239
+ end
240
+
241
+ # Push value into a multiple field
242
+ # @param [String] path The field name on which the operation is to be applied
243
+ # @param [#read] value Any value you wish to push
244
+ # @param [Fixnum] index The index at which to push
245
+ # @return [Object] self
246
+ def push_value(path, value, index=nil)
247
+ # TODO: also handle ability to push at nested multiples
248
+ Util.type_check("path", path, String)
249
+ Util.type_check("index", index, Fixnum) if index
250
+
251
+ value = value.is_a?(Array) ? value : [value]
252
+
253
+ self[path] = {
254
+ "PUSH" => {
255
+ "data" => value
256
+ }
257
+ }
258
+
259
+ if index
260
+ self[path]["PUSH"]["index"] = index
261
+ end
262
+
263
+ self
264
+ end
265
+
266
+ # Get the location object for this object
267
+ # @return [Location]
268
+ def location
269
+ loc = self[Built::LOCATION_PATH]
270
+ if loc
271
+ Location.new(loc[0], loc[1])
272
+ else
273
+ nil
274
+ end
275
+ end
276
+
277
+ # Set the location
278
+ # @param [Location] loc The location object to set
279
+ def location=(loc)
280
+ Util.type_check("loc", loc, Location)
281
+
282
+ self[Built::LOCATION_PATH] = loc.to_arr
283
+
284
+ self
285
+ end
286
+
287
+ # Get ACL
288
+ # @return [ACL]
289
+ def ACL
290
+ Built::ACL.new(self["ACL"])
291
+ end
292
+
293
+ # Set ACL
294
+ # @param [ACL] acl
295
+ # @return [Object] self
296
+ def ACL=(acl)
297
+ self["ACL"] = {
298
+ "disable" => acl.disabled,
299
+ "others" => acl.others,
300
+ "users" => acl.users,
301
+ "roles" => acl.roles
302
+ }
303
+
304
+ self
305
+ end
306
+
307
+ # Get the version this object is on
308
+ def version
309
+ self["_version"]
310
+ end
311
+
312
+ # Unpublish this object
313
+ # @return [Object] self
314
+ def unpublish
315
+ self["published"] = false
316
+ self
317
+ end
318
+
319
+ # Publish this object
320
+ # @return [Object] self
321
+ def publish
322
+ self["published"] = true
323
+ self
324
+ end
325
+
326
+ # Is this object published?
327
+ # @return [Boolean]
328
+ def is_published?
329
+ self["published"]
330
+ end
331
+
332
+ # Get tags for this object
333
+ def tags
334
+ self["tags"] || []
335
+ end
336
+
337
+ # Add new tags
338
+ # @param [Array<String>] tags An array of strings. Can also be a single tag.
339
+ # @return [Object] self
340
+ def add_tags(tags)
341
+ tags = tags.is_a?(Array) ? tags : [tags]
342
+ self["tags"] ||= []
343
+ self["tags"].concat(tags)
344
+ self
345
+ end
346
+
347
+ # Remove tags
348
+ # @param [Array<String>] tags An array of strings. Can also be a single tag.
349
+ # @return [Object] self
350
+ def remove_tags(tags)
351
+ tags = tags.is_a?(Array) ? tags : [tags]
352
+ self["tags"] ||= []
353
+ self["tags"] = self["tags"] - tags
354
+ self
355
+ end
83
356
 
84
357
  # Is this a new, unsaved object?
85
358
  # @return [Boolean]
86
359
  def is_new?
87
- Util.blank?(self["uid"])
360
+ Util.blank?(uid)
88
361
  end
89
362
 
90
363
  # Initialize a new object
91
364
  # @param [String] class_uid The uid of the class to which this object belongs
92
- # @param [Hash] data Data to initialize the object with
93
- def initialize(class_uid, data=nil)
365
+ # @param [String] uid The uid of an existing object, if this is an existing object
366
+ def initialize(class_uid, uid=nil)
94
367
  if !class_uid
95
368
  raise BuiltError, I18n.t("objects.class_uid")
96
369
  end
97
370
 
98
371
  @class_uid = class_uid
99
372
 
100
- if data
101
- instantiate(data)
373
+ if uid
374
+ self.uid = uid
102
375
  end
103
376
 
377
+ clean_up!
104
378
  self
105
379
  end
106
380
 
@@ -131,6 +405,7 @@ module Built
131
405
  end
132
406
 
133
407
  class << self
408
+ # @api private
134
409
  def instantiate(data)
135
410
  doc = new
136
411
  doc.instantiate(data)
data/lib/built/query.rb CHANGED
@@ -24,136 +24,196 @@ module Built
24
24
  }
25
25
  end
26
26
 
27
- # Where given key matches value
28
- # @param [String] key The key on which to search
27
+ # Where given field matches value
28
+ # @param [String] field The field on which to search
29
29
  # @param [Object] value The value with which to match
30
30
  # @return [Query] self
31
- def where(key, value)
32
- @params["query"][key] = value
31
+ def where(field, value)
32
+ @params["query"][field] = value
33
33
 
34
34
  self
35
35
  end
36
36
 
37
- # To check that the key has a value greater than the one specified
38
- # @param [String] key The key
37
+ # To check that the field has a value greater than the one specified
38
+ # @param [String] field The field
39
39
  # @param [Object] value The value
40
40
  # @return [Query] self
41
- def greater_than(key, value)
42
- @params["query"][key] = {"$gt" => value}
41
+ def greater_than(field, value)
42
+ @params["query"][field] = {"$gt" => value}
43
43
 
44
44
  self
45
45
  end
46
46
 
47
- # To check that the key has a value greater than OR equaling the one specified
48
- # @param [String] key The key
47
+ # To check that the field has a value greater than OR equaling the one specified
48
+ # @param [String] field The field
49
49
  # @param [Object] value The value
50
50
  # @return [Query] self
51
- def greater_than_equal(key, value)
52
- @params["query"][key] = {"$gte" => value}
51
+ def greater_than_equal(field, value)
52
+ @params["query"][field] = {"$gte" => value}
53
53
 
54
54
  self
55
55
  end
56
56
 
57
- # To check that the key has a value less than the one specified
58
- # @param [String] key The key
57
+ # To check that the field has a value less than the one specified
58
+ # @param [String] field The field
59
59
  # @param [Object] value The value
60
60
  # @return [Query] self
61
- def less_than(key, value)
62
- @params["query"][key] = {"$lt" => value}
61
+ def less_than(field, value)
62
+ @params["query"][field] = {"$lt" => value}
63
63
 
64
64
  self
65
65
  end
66
66
 
67
- # To check that the key has a value less than OR equaling the one specified
68
- # @param [String] key The key
67
+ # To check that the field has a value less than OR equaling the one specified
68
+ # @param [String] field The field
69
69
  # @param [Object] value The value
70
70
  # @return [Query] self
71
- def less_than_equal(key, value)
72
- @params["query"][key] = {"$lte" => value}
71
+ def less_than_equal(field, value)
72
+ @params["query"][field] = {"$lte" => value}
73
73
 
74
74
  self
75
75
  end
76
76
 
77
- # To check that the key has a value not equaling the one specified
78
- # @param [String] key The key
77
+ # To check that the field has a value not equaling the one specified
78
+ # @param [String] field The field
79
79
  # @param [Object] value The value
80
80
  # @return [Query] self
81
- def not_equal(key, value)
82
- @params["query"][key] = {"$ne" => value}
81
+ def not_equal(field, value)
82
+ @params["query"][field] = {"$ne" => value}
83
83
 
84
84
  self
85
85
  end
86
86
 
87
- # Sort results in ascending order for the given key
88
- # @param [String] key The key by which to sort
87
+ # Sort results in ascending order for the given field
88
+ # @param [String] field The field by which to sort
89
89
  # @return [Query] self
90
- def ascending(key)
91
- @params["asc"] = key
90
+ def ascending(field)
91
+ @params["asc"] = field
92
92
 
93
93
  self
94
94
  end
95
95
 
96
- # Sort results in descending order for the given key
97
- # @param [String] key The key by which to sort
96
+ # Sort results in descending order for the given field
97
+ # @param [String] field The field by which to sort
98
98
  # @return [Query] self
99
- def descending(key)
100
- @params["desc"] = key
99
+ def descending(field)
100
+ @params["desc"] = field
101
101
 
102
102
  self
103
103
  end
104
104
 
105
- # To check that the value for a key is contained in a given array
106
- # @param [String] key The key to check
105
+ # To check that the value for a field is contained in a given array
106
+ # @param [String] field The field to check
107
107
  # @param [Array] array An array of values
108
108
  # @return [Query] self
109
- def contained_in(key, array)
110
- @params["query"][key] = {"$in" => array}
109
+ def contained_in(field, array)
110
+ @params["query"][field] = {"$in" => array}
111
111
 
112
112
  self
113
113
  end
114
114
 
115
- # To check that the value for a key is NOT contained in a given array
116
- # @param [String] key The key to check
115
+ # To check that the value for a field is NOT contained in a given array
116
+ # @param [String] field The field to check
117
117
  # @param [Array] array An array of values
118
118
  # @return [Query] self
119
- def not_contained_in(key, array)
120
- @params["query"][key] = {"$nin" => array}
119
+ def not_contained_in(field, array)
120
+ @params["query"][field] = {"$nin" => array}
121
121
 
122
122
  self
123
123
  end
124
124
 
125
- # To check that the given key exists
126
- # @param [String] key
125
+ # To check that the given field exists
126
+ # @param [String] field
127
127
  # @return [Query] self
128
- def exists(key)
129
- @params["query"][key] = {"$exists" => true}
128
+ def exists(field)
129
+ @params["query"][field] = {"$exists" => true}
130
130
 
131
131
  self
132
132
  end
133
133
 
134
- # To check that the given key does not exist
135
- # @param [String] key
134
+ # To check that the given field does not exist
135
+ # @param [String] field
136
136
  # @return [Query] self
137
- def not_exists(key)
138
- @params["query"][key] = {"$exists" => false}
137
+ def not_exists(field)
138
+ @params["query"][field] = {"$exists" => false}
139
139
 
140
140
  self
141
141
  end
142
142
 
143
143
  # Reference query a field
144
- # @param [String] key
144
+ # @param [String] field
145
145
  # @param [Query] query
146
- def in_query(key, query)
147
- @params["query"][key] = {"$in_query" => query.params["query"]}
146
+ def in_query(field, query)
147
+ @params["query"][field] = {"$in_query" => query.params["query"]}
148
148
 
149
149
  self
150
150
  end
151
151
 
152
152
  # Reference query a field negatively
153
- # @param [String] key
153
+ # @param [String] field
154
154
  # @param [Query] query
155
- def not_in_query(key, query)
156
- @params["query"][key] = {"$nin_query" => query.params["query"]}
155
+ def not_in_query(field, query)
156
+ @params["query"][field] = {"$nin_query" => query.params["query"]}
157
+
158
+ self
159
+ end
160
+
161
+ # Select query a field for arbitrary references
162
+ # @param [String] field The field to query
163
+ # @param [String] class_uid of the class to query
164
+ # @param [String] key to match
165
+ # @param [Query] query to execute on the class
166
+ def select_query(field, class_uid, key, query)
167
+ @params["query"][field] = {
168
+ "$select" => {
169
+ "key" => key,
170
+ "class_uid" => class_uid,
171
+ "query" => query
172
+ }
173
+ }
174
+
175
+ self
176
+ end
177
+
178
+ # Select query a field for arbitrary references, negatively
179
+ # @param [String] field The field to query
180
+ # @param [String] class_uid of the class to query
181
+ # @param [String] key to match
182
+ # @param [Query] query to execute on the class
183
+ def dont_select_query(field, class_uid, key, query)
184
+ @params["query"][field] = {
185
+ "$dont_select" => {
186
+ "key" => key,
187
+ "class_uid" => class_uid,
188
+ "query" => query
189
+ }
190
+ }
191
+
192
+ self
193
+ end
194
+
195
+ # Get objects near a Location or an Object.
196
+ # @param [Location, Object] location The location object or a Built::Object
197
+ # @param [Fixnum] radius The radius in meters
198
+ def near(location, radius)
199
+ @params["query"]["$near"] = {
200
+ "coords" => location.is_a?(Built::Location) ? location.to_arr : {
201
+ "object" => location.uid
202
+ },
203
+ "radius" => radius
204
+ }
205
+
206
+ self
207
+ end
208
+
209
+ # Get objects within a set of location points
210
+ # @param [Array<Location, Object>] Set of location points
211
+ def within(points)
212
+ @params["query"]["$within"] = points.map do |point|
213
+ point.is_a?(Built::Location) ? location.to_arr : {
214
+ "object" => location.uid
215
+ }
216
+ end
157
217
 
158
218
  self
159
219
  end
@@ -193,11 +253,11 @@ module Built
193
253
  end
194
254
 
195
255
  # Include reference fields in the response (joins)
196
- # @param [String] key The reference field to include
256
+ # @param [String] field The reference field to include
197
257
  # @return [Query] self
198
- def include(key)
258
+ def include(field)
199
259
  @params["include"] ||= []
200
- @params["include"] << key
260
+ @params["include"] << field
201
261
 
202
262
  self
203
263
  end
@@ -236,7 +296,7 @@ module Built
236
296
  uri = Built::Object.uri(@class_uid)
237
297
 
238
298
  QueryResponse.new(
239
- Built.client.request(uri, :get, nil, @params).parsed_response,
299
+ Built.client.request(uri, :get, nil, @params).json,
240
300
  @class_uid
241
301
  )
242
302
  end
@@ -266,8 +326,18 @@ module Built
266
326
  def initialize(response, class_uid)
267
327
  @response = response
268
328
 
329
+ obj_class = Built::Object
330
+ case class_uid
331
+ when Built::USER_CLASS_UID
332
+ obj_class = Built::User
333
+ when Built::ROLE_CLASS_UID
334
+ obj_class = Built::Role
335
+ when Built::INST_CLASS_UID
336
+ obj_class = Built::Installation
337
+ end
338
+
269
339
  if response["objects"].is_a?(Array)
270
- @objects = response["objects"].map {|o| Built::Object.new(class_uid, o)}
340
+ @objects = response["objects"].map {|o| obj_class.new(class_uid).instantiate(o)}
271
341
  else
272
342
  @objects = []
273
343
  @count = response["objects"]
data/lib/built/role.rb ADDED
@@ -0,0 +1,4 @@
1
+ module Built
2
+ class Role < Built::Object
3
+ end
4
+ end