parse-stack 1.5.1 → 1.5.2

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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +15 -1
  3. data/Gemfile.lock +10 -10
  4. data/README.md +23 -9
  5. data/bin/console +3 -0
  6. data/lib/parse/api/analytics.rb +1 -1
  7. data/lib/parse/api/objects.rb +1 -1
  8. data/lib/parse/api/users.rb +1 -1
  9. data/lib/parse/client.rb +77 -40
  10. data/lib/parse/client/caching.rb +9 -5
  11. data/lib/parse/client/protocol.rb +47 -0
  12. data/lib/parse/client/request.rb +66 -37
  13. data/lib/parse/client/response.rb +39 -21
  14. data/lib/parse/model/acl.rb +4 -9
  15. data/lib/parse/model/associations/belongs_to.rb +97 -9
  16. data/lib/parse/model/associations/collection_proxy.rb +89 -29
  17. data/lib/parse/model/associations/has_many.rb +301 -28
  18. data/lib/parse/model/associations/has_one.rb +98 -4
  19. data/lib/parse/model/associations/pointer_collection_proxy.rb +48 -16
  20. data/lib/parse/model/associations/relation_collection_proxy.rb +61 -36
  21. data/lib/parse/model/bytes.rb +11 -5
  22. data/lib/parse/model/classes/installation.rb +50 -3
  23. data/lib/parse/model/classes/role.rb +7 -2
  24. data/lib/parse/model/classes/session.rb +21 -4
  25. data/lib/parse/model/classes/user.rb +122 -22
  26. data/lib/parse/model/core/actions.rb +7 -3
  27. data/lib/parse/model/core/properties.rb +14 -13
  28. data/lib/parse/model/core/querying.rb +16 -10
  29. data/lib/parse/model/core/schema.rb +2 -3
  30. data/lib/parse/model/date.rb +18 -12
  31. data/lib/parse/model/file.rb +77 -19
  32. data/lib/parse/model/geopoint.rb +70 -12
  33. data/lib/parse/model/model.rb +84 -8
  34. data/lib/parse/model/object.rb +225 -94
  35. data/lib/parse/model/pointer.rb +94 -13
  36. data/lib/parse/model/push.rb +76 -4
  37. data/lib/parse/query.rb +356 -41
  38. data/lib/parse/query/constraints.rb +399 -29
  39. data/lib/parse/query/ordering.rb +21 -8
  40. data/lib/parse/stack.rb +1 -0
  41. data/lib/parse/stack/version.rb +2 -1
  42. data/lib/parse/webhooks.rb +0 -24
  43. data/lib/parse/webhooks/payload.rb +54 -1
  44. data/lib/parse/webhooks/registration.rb +13 -2
  45. metadata +2 -2
@@ -3,20 +3,60 @@
3
3
 
4
4
  require_relative 'constraint'
5
5
 
6
- # Eac constraint type is a subclass of Parse::Constraint
6
+ # Each constraint type is a subclass of Parse::Constraint
7
7
  # We register each keyword (which is the Parse query operator)
8
8
  # and the local operator we want to use. Each of the registered local
9
9
  # operators are added as methods to the Symbol class.
10
10
  # For more information: https://parse.com/docs/rest/guide#queries
11
11
  # For more information about the query design pattern from DataMapper
12
12
  # that inspired this, see http://datamapper.org/docs/find.html
13
- class ParseConstraintError < StandardError; end;
14
- module Parse
15
13
 
14
+
15
+
16
+
17
+ module Parse
18
+ # Error for when there is a problem with the input passed to a constraint.
19
+ class ConstraintError < StandardError; end;
20
+
21
+ # A constraint for matching by a specific objectId value.
22
+ #
23
+ # # where this Parse object equals the object in the column `field`.
24
+ # q.where :field => Parse::Pointer("Field", "someObjectId")
25
+ # # alias, shorthand when we infer `:field` maps to `Field` parse class.
26
+ # q.where :field.id => "someObjectId"
27
+ # # "field":{"__type":"Pointer","className":"Field","objectId":"someObjectId"}}
28
+ #
29
+ # class Artist < Parse::Object
30
+ # end
31
+ #
32
+ # class Song < Parse::Object
33
+ # belongs_to :artist
34
+ # end
35
+ #
36
+ # artist = Artist.first # get any artist
37
+ # artist_id = artist.id # ex. artist.id
38
+ #
39
+ # # find all songs for this artist object
40
+ # Song.all :artist => artist
41
+ # In some cases, you do not have the Parse object, but you have its `objectId`.
42
+ # You can use the objectId in the query as follows:
43
+ #
44
+ # # shorthand if you are using convention. Will infer class `Artist`
45
+ # Song.all :artist.id => artist_id
46
+ #
47
+ # # other approaches, same result
48
+ # Song.all :artist => Artist.pointer(artist_id)
49
+ # Song.all :artist => Parse::Pointer.new("Artist", artist_id)
50
+ #
16
51
  class ObjectIdConstraint < Constraint
52
+ # @!method id
53
+ # A registered method on a symbol to create the constraint.
54
+ # @example
55
+ # q.where :field.id => "someObjectId"
56
+ # @return [ObjectIdConstraint]
17
57
  register :id
18
58
 
19
-
59
+ # @return [Hash] the compiled constraint.
20
60
  def build
21
61
  className = operand.to_parse_class
22
62
  value = formatted_value
@@ -27,14 +67,14 @@ module Parse
27
67
  end
28
68
 
29
69
  unless klass.present? && klass.is_a?(Parse::Object) == false
30
- raise ParseConstraintError, "#{self.class}: No Parse class defined for #{operand} as '#{className}'"
70
+ raise ConstraintError, "#{self.class}: No Parse class defined for #{operand} as '#{className}'"
31
71
  end
32
72
 
33
73
  # allow symbols
34
74
  value = value.to_s if value.is_a?(Symbol)
35
75
 
36
76
  unless value.is_a?(String) && value.strip.present?
37
- raise ParseConstraintError, "#{self.class}: value must be of string type representing a Parse object id."
77
+ raise ConstraintError, "#{self.class}: value must be of string type representing a Parse object id."
38
78
  end
39
79
  value.strip!
40
80
  return { @operation.operand => klass.pointer(value) }
@@ -42,67 +82,171 @@ module Parse
42
82
 
43
83
  end
44
84
 
85
+ # Equivalent to the `$or` Parse query operation. This is useful if you want to
86
+ # find objects that match several queries. We overload the `|` operator in
87
+ # order to have a clean syntax for joining these `or` operations.
88
+ # or_query = query1 | query2 | query3
89
+ # query = Player.where(:wins.gt => 150) | Player.where(:wins.lt => 5)
90
+ #
91
+ # query.or_where :field => value
92
+ #
45
93
  class CompoundQueryConstraint < Constraint
46
94
  contraint_keyword :$or
47
95
  register :or
48
96
 
97
+ # @return [Hash] the compiled constraint.
49
98
  def build
50
99
  or_clauses = formatted_value
51
- or_clauses = [or_clauses] unless or_clauses.is_a?(Array)
52
- return { :$or => or_clauses }
100
+ return { :$or => Array.wrap(or_clauses) }
53
101
  end
54
102
 
55
103
  end
56
104
 
105
+ # Equivalent to the `$lte` Parse query operation. The alias `on_or_before` is provided for readability.
106
+ # q.where :field.lte => value
107
+ # q.where :field.on_or_before => date
108
+ #
109
+ # q.where :created_at.on_or_before => DateTime.now
110
+ # @see LessThanConstraint
57
111
  class LessThanOrEqualConstraint < Constraint
112
+ # @!method lte
113
+ # A registered method on a symbol to create the constraint. Maps to Parse operator "$lte".
114
+ # @example
115
+ # q.where :field.lte => value
116
+ # @return [LessThanOrEqualConstraint]
117
+
118
+ # @!method less_than_or_equal
119
+ # Alias for {lte}
120
+ # @return [LessThanOrEqualConstraint]
121
+
122
+ # @!method on_or_before
123
+ # Alias for {lte} that provides better readability when constraining dates.
124
+ # @return [LessThanOrEqualConstraint]
58
125
  contraint_keyword :$lte
59
126
  register :lte
60
127
  register :less_than_or_equal
61
128
  register :on_or_before
62
129
  end
63
130
 
131
+ # Equivalent to the `$lt` Parse query operation. The alias `before` is provided for readability.
132
+ # q.where :field.lt => value
133
+ # q.where :field.before => date
134
+ #
135
+ # q.where :created_at.before => DateTime.now
64
136
  class LessThanConstraint < Constraint
137
+ # @!method lt
138
+ # A registered method on a symbol to create the constraint. Maps to Parse operator "$lt".
139
+ # @example
140
+ # q.where :field.lt => value
141
+ # @return [LessThanConstraint]
142
+
143
+ # @!method less_than
144
+ # # Alias for {lt}.
145
+ # @return [LessThanConstraint]
146
+
147
+ # @!method before
148
+ # Alias for {lt} that provides better readability when constraining dates.
149
+ # @return [LessThanConstraint]
65
150
  contraint_keyword :$lt
66
151
  register :lt
67
152
  register :less_than
68
153
  register :before
69
154
  end
70
-
155
+ # Equivalent to the `$gt` Parse query operation. The alias `after` is provided for readability.
156
+ # q.where :field.gt => value
157
+ # q.where :field.after => date
158
+ #
159
+ # q.where :created_at.after => DateTime.now
160
+ # @see GreaterThanOrEqualConstraint
71
161
  class GreaterThanConstraint < Constraint
162
+ # @!method gt
163
+ # A registered method on a symbol to create the constraint. Maps to Parse operator "$gt".
164
+ # @example
165
+ # q.where :field.gt => value
166
+ # @return [GreaterThanConstraint]
167
+
168
+ # @!method greater_than
169
+ # # Alias for {gt}.
170
+ # @return [GreaterThanConstraint]
171
+
172
+ # @!method after
173
+ # Alias for {gt} that provides better readability when constraining dates.
174
+ # @return [GreaterThanConstraint]
72
175
  contraint_keyword :$gt
73
176
  register :gt
74
177
  register :greater_than
75
178
  register :after
76
179
  end
77
180
 
181
+ # Equivalent to the `$gte` Parse query operation. The alias `on_or_after` is provided for readability.
182
+ # q.where :field.gte => value
183
+ # q.where :field.on_or_after => date
184
+ #
185
+ # q.where :created_at.on_or_after => DateTime.now
186
+ # @see GreaterThanConstraint
78
187
  class GreaterThanOrEqualConstraint < Constraint
188
+ # @!method gte
189
+ # A registered method on a symbol to create the constraint. Maps to Parse operator "$gte".
190
+ # @example
191
+ # q.where :field.gte => value
192
+ # @return [GreaterThanOrEqualConstraint]
193
+
194
+ # @!method greater_than_or_equal
195
+ # # Alias for {gte}.
196
+ # @return [GreaterThanOrEqualConstraint]
197
+
198
+ # @!method on_or_after
199
+ # Alias for {gte} that provides better readability when constraining dates.
200
+ # @return [GreaterThanOrEqualConstraint]
79
201
  contraint_keyword :$gte
80
202
  register :gte
81
203
  register :greater_than_or_equal
82
204
  register :on_or_after
83
205
  end
84
206
 
207
+ # Equivalent to the `$ne` Parse query operation. Where a particular field is not equal to value.
208
+ # q.where :field.not => value
85
209
  class NotEqualConstraint < Constraint
210
+ # @!method not
211
+ # A registered method on a symbol to create the constraint. Maps to Parse operator "$ne".
212
+ # @example
213
+ # q.where :field.not => value
214
+ # @return [NotEqualConstraint]
215
+
216
+ # @!method ne
217
+ # # Alias for {not}.
218
+ # @return [NotEqualConstraint]
86
219
  contraint_keyword :$ne
87
220
  register :not
88
221
  register :ne
89
222
  end
90
223
 
91
- # Nullabiliity constraint maps $exist Parse clause a bit differently
92
- # Parse currently has a bug that if you select items near a location
93
- # and want to make sure a different column has a value, you need to
94
- # search where the column does not contani a null/undefined value.
95
- # Therefore we override the build method to change the operation to a
96
- # NotEqualConstraint
224
+ # Provides a mechanism using the equality operator to check for `(undefined)` values.
225
+ # Nullabiliity constraint maps the `$exists` Parse clause to enable checking for
226
+ # existance in a column when performing geoqueries due to a Parse limitation.
227
+ # q.where :field.null => false
228
+ # @note Parse currently has a bug that if you select items near a location
229
+ # and want to make sure a different column has a value, you need to
230
+ # search where the column does not contanin a null/undefined value.
231
+ # Therefore we override the build method to change the operation to a
232
+ # {NotEqualConstraint}.
233
+ # @see ExistsConstraint
97
234
  class NullabilityConstraint < Constraint
235
+ # @!method null
236
+ # A registered method on a symbol to create the constraint.
237
+ # @example
238
+ # q.where :field.null => true
239
+ # @return [NullabilityConstraint]
98
240
  contraint_keyword :$exists
99
241
  register :null
242
+
243
+ # @return [Hash] the compiled constraint.
100
244
  def build
101
245
  # if nullability is equal true, then $exists should be set to false
102
246
 
103
247
  value = formatted_value
104
248
  unless value == true || value == false
105
- raise ParseConstraintError, "#{self.class}: Non-Boolean value passed, it must be either `true` or `false`"
249
+ raise ConstraintError, "#{self.class}: Non-Boolean value passed, it must be either `true` or `false`"
106
250
  end
107
251
 
108
252
  if value == true
@@ -116,27 +260,58 @@ module Parse
116
260
  end
117
261
  end
118
262
 
263
+ # Equivalent to the `#exists` Parse query operation. Checks whether a value is
264
+ # set for key. The difference between this operation and the nullability check
265
+ # is when using compound queries with location.
266
+ # q.where :field.exists => true
267
+ #
268
+ # @see NullabilityConstraint
119
269
  class ExistsConstraint < Constraint
270
+ # @!method exists
271
+ # A registered method on a symbol to create the constraint. Maps to Parse operator "$exists".
272
+ # @example
273
+ # q.where :field.exists => true
274
+ # @return [ExistsConstraint]
120
275
  contraint_keyword :$exists
121
276
  register :exists
277
+
278
+ # @return [Hash] the compiled constraint.
122
279
  def build
123
280
  # if nullability is equal true, then $exists should be set to false
124
281
  value = formatted_value
125
282
 
126
283
  unless value == true || value == false
127
- raise ParseConstraintError, "#{self.class}: Non-Boolean value passed, it must be either `true` or `false`"
284
+ raise ConstraintError, "#{self.class}: Non-Boolean value passed, it must be either `true` or `false`"
128
285
  end
129
286
 
130
287
  return { @operation.operand => { key => value } }
131
288
  end
132
289
  end
133
290
 
134
- # Mapps all items contained in the array
291
+ # Equivalent to the `$in` Parse query operation. Checks whether the value in the
292
+ # column field is contained in the set of values in the target array. If the
293
+ # field is an array data type, it checks whether at least one value in the
294
+ # field array is contained in the set of values in the target array.
295
+ # q.where :field.in => array
296
+ # q.where :score.in => [1,3,5,7,9]
297
+ #
298
+ # @see ContainsAllConstraint
299
+ # @see NotContainedInConstraint
135
300
  class ContainedInConstraint < Constraint
301
+ # @!method in
302
+ # A registered method on a symbol to create the constraint. Maps to Parse operator "$in".
303
+ # @example
304
+ # q.where :field.in => array
305
+ # @return [ContainedInConstraint]
306
+
307
+ # @!method contained_in
308
+ # Alias for {in}
309
+ # @return [ContainedInConstraint]
136
310
  contraint_keyword :$in
137
311
  register :in
138
312
  register :contained_in
139
313
 
314
+ # @return [Hash] the compiled constraint.
140
315
  def build
141
316
  val = formatted_value
142
317
  val = [val].compact unless val.is_a?(Array)
@@ -145,12 +320,36 @@ module Parse
145
320
 
146
321
  end
147
322
 
323
+ # Equivalent to the `$nin` Parse query operation. Checks whether the value in
324
+ # the column field is *not* contained in the set of values in the target
325
+ # array. If the field is an array data type, it checks whether at least one
326
+ # value in the field array is *not* contained in the set of values in the
327
+ # target array.
328
+ #
329
+ # q.where :field.not_in => array
330
+ # q.where :player_name.not_in => ["Jonathan", "Dario", "Shawn"]
331
+ # @see ContainedInConstraint
332
+ # @see ContainsAllConstraint
148
333
  class NotContainedInConstraint < Constraint
334
+ # @!method not_in
335
+ # A registered method on a symbol to create the constraint. Maps to Parse operator "$nin".
336
+ # @example
337
+ # q.where :field.not_in => array
338
+ # @return [NotContainedInConstraint]
339
+
340
+ # @!method nin
341
+ # Alias for {not_in}
342
+ # @return [NotContainedInConstraint]
343
+
344
+ # @!method not_contained_in
345
+ # Alias for {not_in}
346
+ # @return [NotContainedInConstraint]
149
347
  contraint_keyword :$nin
150
348
  register :not_in
151
349
  register :nin
152
350
  register :not_contained_in
153
351
 
352
+ # @return [Hash] the compiled constraint.
154
353
  def build
155
354
  val = formatted_value
156
355
  val = [val].compact unless val.is_a?(Array)
@@ -159,12 +358,30 @@ module Parse
159
358
 
160
359
  end
161
360
 
162
- # All Things must be contained
361
+ # Equivalent to the $all Parse query operation. Checks whether the value in
362
+ # the column field contains all of the given values provided in the array. Note
363
+ # that the field column should be of type {Array} in your Parse class.
364
+ #
365
+ # q.where :field.all => array
366
+ # q.where :array_key.all => [2,3,4]
367
+ #
368
+ # @see ContainedInConstraint
369
+ # @see NotContainedInConstraint
163
370
  class ContainsAllConstraint < Constraint
371
+ # @!method all
372
+ # A registered method on a symbol to create the constraint. Maps to Parse operator "$all".
373
+ # @example
374
+ # q.where :field.all => array
375
+ # @return [ContainsAllConstraint]
376
+
377
+ # @!method contains_all
378
+ # Alias for {all}
379
+ # @return [ContainsAllConstraint]
164
380
  contraint_keyword :$all
165
381
  register :all
166
382
  register :contains_all
167
383
 
384
+ # @return [Hash] the compiled constraint.
168
385
  def build
169
386
  val = formatted_value
170
387
  val = [val].compact unless val.is_a?(Array)
@@ -172,11 +389,26 @@ module Parse
172
389
  end
173
390
  end
174
391
 
392
+ # Equivalent to the `$select` Parse query operation. This matches a value for a
393
+ # key in the result of a different query.
394
+ # q.where :field.select => { key: "field", query: query }
395
+ #
396
+ # # example
397
+ # value = { key: 'city', query: Artist.where(:fan_count.gt => 50) }
398
+ # q.where :hometown.select => value
399
+ #
400
+ # # if the local field is the same name as the foreign table field, you can omit hash
401
+ # # assumes key: 'city'
402
+ # q.where :city.select => Artist.where(:fan_count.gt => 50)
403
+ #
175
404
  class SelectionConstraint < Constraint
176
- #This matches a value for a key in the result of a different query
405
+ # @!method select
406
+ # A registered method on a symbol to create the constraint. Maps to Parse operator "$select".
407
+ # @return [SelectionConstraint]
177
408
  contraint_keyword :$select
178
409
  register :select
179
410
 
411
+ # @return [Hash] the compiled constraint.
180
412
  def build
181
413
 
182
414
  # if it's a hash, then it should be {:key=>"objectId", :query=>[]}
@@ -187,24 +419,48 @@ module Parse
187
419
  remote_field_name = res[:key] || remote_field_name
188
420
  query = res[:query]
189
421
  unless query.is_a?(Parse::Query)
190
- raise ParseConstraintError, "Invalid Parse::Query object provided in :query field of value: #{@operation.operand}.#{$dontSelect} => #{@value}"
422
+ raise ConstraintError, "Invalid Parse::Query object provided in :query field of value: #{@operation.operand}.#{$dontSelect} => #{@value}"
191
423
  end
192
424
  query = query.compile(encode: false, includeClassName: true)
193
425
  elsif @value.is_a?(Parse::Query)
194
426
  # if its a query, then assume dontSelect key is the same name as operand.
195
427
  query = @value.compile(encode: false, includeClassName: true)
196
428
  else
197
- raise ParseConstraintError, "Invalid `:select` query constraint. It should follow the format: :field.select => { key: 'key', query: '<Parse::Query>' }"
429
+ raise ConstraintError, "Invalid `:select` query constraint. It should follow the format: :field.select => { key: 'key', query: '<Parse::Query>' }"
198
430
  end
199
431
  { @operation.operand => { :$select => { key: remote_field_name, query: query } } }
200
432
  end
201
433
  end
202
434
 
435
+ # Equivalent to the `$dontSelect` Parse query operation. Requires that a field's
436
+ # value not match a value for a key in the result of a different query.
437
+ #
438
+ # q.where :field.reject => { key: :other_field, query: query }
439
+ #
440
+ # value = { key: 'city', query: Artist.where(:fan_count.gt => 50) }
441
+ # q.where :hometown.reject => value
442
+ #
443
+ # # if the local field is the same name as the foreign table field, you can omit hash
444
+ # # assumes key: 'city'
445
+ # q.where :city.reject => Artist.where(:fan_count.gt => 50)
446
+ #
447
+ # @see SelectionConstraint
203
448
  class RejectionConstraint < Constraint
204
- #requires that a key's value not match a value for a key in the result of a different query
449
+
450
+ # @!method dont_select
451
+ # A registered method on a symbol to create the constraint. Maps to Parse operator "$dontSelect".
452
+ # @example
453
+ # q.where :field.reject => { key: :other_field, query: query }
454
+ # @return [RejectionConstraint]
455
+
456
+ # @!method reject
457
+ # Alias for {dont_select}
458
+ # @return [RejectionConstraint]
205
459
  contraint_keyword :$dontSelect
206
- register :dont_select
207
460
  register :reject
461
+ register :dont_select
462
+
463
+ # @return [Hash] the compiled constraint.
208
464
  def build
209
465
 
210
466
  # if it's a hash, then it should be {:key=>"objectId", :query=>[]}
@@ -215,32 +471,66 @@ module Parse
215
471
  remote_field_name = res[:key] || remote_field_name
216
472
  query = res[:query]
217
473
  unless query.is_a?(Parse::Query)
218
- raise ParseConstraintError, "Invalid Parse::Query object provided in :query field of value: #{@operation.operand}.#{$dontSelect} => #{@value}"
474
+ raise ConstraintError, "Invalid Parse::Query object provided in :query field of value: #{@operation.operand}.#{$dontSelect} => #{@value}"
219
475
  end
220
476
  query = query.compile(encode: false, includeClassName: true)
221
477
  elsif @value.is_a?(Parse::Query)
222
478
  # if its a query, then assume dontSelect key is the same name as operand.
223
479
  query = @value.compile(encode: false, includeClassName: true)
224
480
  else
225
- raise ParseConstraintError, "Invalid `:reject` query constraint. It should follow the format: :field.reject => { key: 'key', query: '<Parse::Query>' }"
481
+ raise ConstraintError, "Invalid `:reject` query constraint. It should follow the format: :field.reject => { key: 'key', query: '<Parse::Query>' }"
226
482
  end
227
483
  { @operation.operand => { :$dontSelect => { key: remote_field_name, query: query } } }
228
484
  end
229
485
  end
230
486
 
487
+ # Equivalent to the `$regex` Parse query operation. Requires that a field value
488
+ # match a regular expression.
489
+ #
490
+ # q.where :field.like => /ruby_regex/i
491
+ # :name.like => /Bob/i
492
+ #
231
493
  class RegularExpressionConstraint < Constraint
232
494
  #Requires that a key's value match a regular expression
495
+
496
+ # @!method like
497
+ # A registered method on a symbol to create the constraint. Maps to Parse operator "$regex".
498
+ # @example
499
+ # q.where :field.like => /ruby_regex/i
500
+ # @return [RegularExpressionConstraint]
501
+
502
+ # @!method regex
503
+ # Alias for {like}
504
+ # @return [RegularExpressionConstraint]
233
505
  contraint_keyword :$regex
234
506
  register :like
235
507
  register :regex
236
508
  end
237
509
 
238
- # Does the propert relational constraint.
510
+ # Equivalent to the `$relatedTo` Parse query operation. If you want to
511
+ # retrieve objects that are members of a `Relation` field in your Parse class.
512
+ #
513
+ # q.where :field.related_to => pointer
514
+ #
515
+ # # find all Users who have liked this post object
516
+ # post = Post.first
517
+ # users = Parse::User.all :likes.related_to => post
518
+ #
239
519
  class RelationQueryConstraint < Constraint
240
- # matches objects in a specific column in a different class table
520
+ # @!method related_to
521
+ # A registered method on a symbol to create the constraint. Maps to Parse operator "$relatedTo".
522
+ # @example
523
+ # q.where :field.related_to => pointer
524
+ # @return [RelationQueryConstraint]
525
+
526
+ # @!method rel
527
+ # Alias for {related_to}
528
+ # @return [RelationQueryConstraint]
241
529
  contraint_keyword :$relatedTo
242
530
  register :related_to
243
531
  register :rel
532
+
533
+ # @return [Hash] the compiled constraint.
244
534
  def build
245
535
  # pointer = formatted_value
246
536
  # unless pointer.is_a?(Parse::Pointer)
@@ -250,23 +540,83 @@ module Parse
250
540
  end
251
541
  end
252
542
 
543
+ # Equivalent to the `$inQuery` Parse query operation. Useful if you want to
544
+ # retrieve objects where a field contains an object that matches another query.
545
+ #
546
+ # q.where :field.matches => query
547
+ # # assume Post class has an image column.
548
+ # q.where :post.matches => Post.where(:image.exists => true )
549
+ #
253
550
  class InQueryConstraint < Constraint
551
+ # @!method matches
552
+ # A registered method on a symbol to create the constraint. Maps to Parse operator "$inQuery".
553
+ # @example
554
+ # q.where :field.matches => query
555
+ # @return [InQueryConstraint]
556
+
557
+ # @!method in_query
558
+ # Alias for {matches}
559
+ # @return [InQueryConstraint]
254
560
  contraint_keyword :$inQuery
255
561
  register :matches
256
562
  register :in_query
257
563
  end
258
564
 
565
+ # Equivalent to the `$notInQuery` Parse query operation. Useful if you want to
566
+ # retrieve objects where a field contains an object that does not match another query.
567
+ # This is the inverse of the {InQueryConstraint}.
568
+ #
569
+ # q.where :field.excludes => query
570
+ #
571
+ # q.where :post.excludes => Post.where(:image.exists => true
572
+ #
259
573
  class NotInQueryConstraint < Constraint
574
+ # @!method excludes
575
+ # A registered method on a symbol to create the constraint. Maps to Parse operator "$notInQuery".
576
+ # @example
577
+ # q.where :field.excludes => query
578
+ # @return [NotInQueryConstraint]
579
+
580
+ # @!method not_in_query
581
+ # Alias for {excludes}
582
+ # @return [NotInQueryConstraint]
260
583
  contraint_keyword :$notInQuery
261
584
  register :excludes
262
585
  register :not_in_query
263
586
 
264
587
  end
265
588
 
589
+ # Equivalent to the `$nearSphere` Parse query operation. This is only applicable
590
+ # if the field is of type `GeoPoint`. This will query Parse and return a list of
591
+ # results ordered by distance with the nearest object being first.
592
+ #
593
+ # q.where :field.near => geopoint
594
+ #
595
+ # geopoint = Parse::GeoPoint.new(30.0, -20.0)
596
+ # PlaceObject.all :location.near => geopoint
597
+ # If you wish to constrain the geospatial query to a maximum number of _miles_,
598
+ # you can utilize the `max_miles` method on a `Parse::GeoPoint` object. This
599
+ # is equivalent to the `$maxDistanceInMiles` constraint used with `$nearSphere`.
600
+ #
601
+ # q.where :field.near => geopoint.max_miles(distance)
602
+ # # or provide a triplet includes max miles constraint
603
+ # q.where :field.near => [lat, lng, miles]
604
+ #
605
+ # geopoint = Parse::GeoPoint.new(30.0, -20.0)
606
+ # PlaceObject.all :location.near => geopoint.max_miles(10)
607
+ #
608
+ # @todo Add support $maxDistanceInKilometers (for kms) and $maxDistanceInRadians (for radian angle).
266
609
  class NearSphereQueryConstraint < Constraint
610
+ # @!method near
611
+ # A registered method on a symbol to create the constraint. Maps to Parse operator "$nearSphere".
612
+ # @example
613
+ # q.where :field.near => geopoint
614
+ # q.where :field.near => geopoint.max_miles(distance)
615
+ # @return [NearSphereQueryConstraint]
267
616
  contraint_keyword :$nearSphere
268
617
  register :near
269
618
 
619
+ # @return [Hash] the compiled constraint.
270
620
  def build
271
621
  point = formatted_value
272
622
  max_miles = nil
@@ -282,15 +632,35 @@ module Parse
282
632
 
283
633
  end
284
634
 
635
+ # Equivalent to the `$within` Parse query operation and `$box` geopoint
636
+ # constraint. The rectangular bounding box is defined by a southwest point as
637
+ # the first parameter, followed by the a northeast point. Please note that Geo
638
+ # box queries that cross the international date lines are not currently
639
+ # supported by Parse.
640
+ #
641
+ # q.where :field.within_box => [soutwestGeoPoint, northeastGeoPoint]
642
+ #
643
+ # sw = Parse::GeoPoint.new 32.82, -117.23 # San Diego
644
+ # ne = Parse::GeoPoint.new 36.12, -115.31 # Las Vegas
645
+ #
646
+ # # get all PlaceObjects inside this bounding box
647
+ # PlaceObject.all :location.within_box => [sw,ne]
648
+ #
285
649
  class WithinGeoBoxQueryConstraint < Constraint
650
+ # @!method within_box
651
+ # A registered method on a symbol to create the constraint. Maps to Parse operator "$within".
652
+ # @example
653
+ # q.where :field.within_box => [soutwestGeoPoint, northeastGeoPoint]
654
+ # @return [WithinGeoBoxQueryConstraint]
286
655
  contraint_keyword :$within
287
656
  register :within_box
288
657
 
658
+ # @return [Hash] the compiled constraint.
289
659
  def build
290
660
  geopoint_values = formatted_value
291
661
  unless geopoint_values.is_a?(Array) && geopoint_values.count == 2 &&
292
662
  geopoint_values.first.is_a?(Parse::GeoPoint) && geopoint_values.last.is_a?(Parse::GeoPoint)
293
- raise(ParseConstraintError, '[Parse::Query] Invalid query value parameter passed to `within_box` constraint. ' +
663
+ raise(ConstraintError, '[Parse::Query] Invalid query value parameter passed to `within_box` constraint. ' +
294
664
  'Values in array must be `Parse::GeoPoint` objects and ' +
295
665
  'it should be in an array format: [southwestPoint, northeastPoint]' )
296
666
  end