parse-stack 1.5.1 → 1.5.2

Sign up to get free protection for your applications and to get access to all the features.
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