parse-stack 1.5.3 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/parse-ruby-sdk.png +0 -0
- data/Changes.md +25 -1
- data/Gemfile.lock +4 -4
- data/README.md +37 -31
- data/bin/console +3 -0
- data/lib/parse/api/all.rb +2 -1
- data/lib/parse/api/apps.rb +12 -0
- data/lib/parse/api/config.rb +5 -1
- data/lib/parse/api/files.rb +1 -0
- data/lib/parse/api/hooks.rb +1 -0
- data/lib/parse/api/objects.rb +4 -1
- data/lib/parse/api/push.rb +1 -0
- data/lib/parse/api/{schemas.rb → schema.rb} +7 -0
- data/lib/parse/api/server.rb +44 -0
- data/lib/parse/api/sessions.rb +1 -0
- data/lib/parse/api/users.rb +4 -1
- data/lib/parse/client.rb +109 -73
- data/lib/parse/client/authentication.rb +2 -1
- data/lib/parse/client/batch.rb +9 -1
- data/lib/parse/client/body_builder.rb +16 -1
- data/lib/parse/client/caching.rb +15 -13
- data/lib/parse/client/protocol.rb +27 -15
- data/lib/parse/client/response.rb +26 -8
- data/lib/parse/model/acl.rb +1 -1
- data/lib/parse/model/associations/belongs_to.rb +18 -19
- data/lib/parse/model/associations/collection_proxy.rb +6 -0
- data/lib/parse/model/associations/has_many.rb +5 -6
- data/lib/parse/model/bytes.rb +4 -1
- data/lib/parse/model/classes/user.rb +46 -44
- data/lib/parse/model/core/actions.rb +508 -460
- data/lib/parse/model/core/builder.rb +75 -0
- data/lib/parse/model/core/errors.rb +9 -0
- data/lib/parse/model/core/fetching.rb +42 -38
- data/lib/parse/model/core/properties.rb +46 -27
- data/lib/parse/model/core/querying.rb +231 -228
- data/lib/parse/model/core/schema.rb +76 -74
- data/lib/parse/model/date.rb +10 -2
- data/lib/parse/model/file.rb +16 -2
- data/lib/parse/model/geopoint.rb +9 -2
- data/lib/parse/model/model.rb +38 -7
- data/lib/parse/model/object.rb +60 -19
- data/lib/parse/model/pointer.rb +22 -1
- data/lib/parse/model/push.rb +6 -2
- data/lib/parse/query.rb +57 -11
- data/lib/parse/query/constraint.rb +5 -2
- data/lib/parse/query/constraints.rb +588 -589
- data/lib/parse/query/ordering.rb +2 -2
- data/lib/parse/stack.rb +1 -0
- data/lib/parse/stack/version.rb +1 -1
- data/lib/parse/webhooks.rb +30 -29
- data/lib/parse/webhooks/payload.rb +181 -168
- data/lib/parse/webhooks/registration.rb +1 -1
- data/parse-stack.gemspec +9 -9
- metadata +9 -12
data/lib/parse/model/pointer.rb
CHANGED
@@ -65,7 +65,7 @@ module Parse
|
|
65
65
|
#
|
66
66
|
# @see Parse::Object
|
67
67
|
class Pointer < Model
|
68
|
-
#
|
68
|
+
# The default attributes in a Parse Pointer hash.
|
69
69
|
ATTRIBUTES = { __type: :string, className: :string, objectId: :string}.freeze
|
70
70
|
# @return [String] the name of the Parse class for this pointer.
|
71
71
|
attr_accessor :parse_class
|
@@ -155,6 +155,27 @@ module Parse
|
|
155
155
|
def present?
|
156
156
|
parse_class.present? && @id.present?
|
157
157
|
end
|
158
|
+
|
159
|
+
# Access the pointer properties through hash accessor. This is done for
|
160
|
+
# compatibility with the hash access of a Parse::Object. This method
|
161
|
+
# returns nil if the key is not one of: :id, :objectId, or :className.
|
162
|
+
# @param key [String] the name of the property.
|
163
|
+
# @return [Object] the value for this key.
|
164
|
+
def [](key)
|
165
|
+
return nil unless [:id,:objectId,:className].include?(key.to_sym)
|
166
|
+
send(key)
|
167
|
+
end
|
168
|
+
|
169
|
+
# Set the pointer properties through hash accessor. This is done for
|
170
|
+
# compatibility with the hash access of a Parse::Object. This method
|
171
|
+
# does nothing if the key is not one of: :id, :objectId, or :className.
|
172
|
+
# @param key (see #[])
|
173
|
+
# @return [Object]
|
174
|
+
def []=(key,value)
|
175
|
+
return unless [:id,:objectId,:className].include?(key.to_sym)
|
176
|
+
send("#{key}=",value)
|
177
|
+
end
|
178
|
+
|
158
179
|
end
|
159
180
|
|
160
181
|
end
|
data/lib/parse/model/push.rb
CHANGED
@@ -89,12 +89,16 @@ module Parse
|
|
89
89
|
@query ||= Parse::Query.new(Parse::Model::CLASS_INSTALLATION)
|
90
90
|
end
|
91
91
|
|
92
|
-
#
|
93
|
-
#
|
92
|
+
# Set a hash of conditions for this push query.
|
93
|
+
# @return [Parse::Query]
|
94
94
|
def where=(where_clausees)
|
95
95
|
query.where where_clauses
|
96
96
|
end
|
97
97
|
|
98
|
+
# Apply a set of constraints.
|
99
|
+
# @param constraints [Hash] the set of {Parse::Query} cosntraints
|
100
|
+
# @return [Hash] if no constraints were passed, returns a compiled query.
|
101
|
+
# @return [Parse::Query] if constraints were passed, returns the chainable query.
|
98
102
|
def where(constraints = nil)
|
99
103
|
return query.compile_where unless constraints.is_a?(Hash)
|
100
104
|
query.where constraints
|
data/lib/parse/query.rb
CHANGED
@@ -150,13 +150,24 @@ module Parse
|
|
150
150
|
# if you do not want any field formatting to be performed.
|
151
151
|
|
152
152
|
@field_formatter = :columnize
|
153
|
+
@allow_scope_introspection = false
|
153
154
|
class << self
|
155
|
+
|
156
|
+
# @!attribute allow_scope_introspection
|
157
|
+
# The attribute will prevent automatically fetching results of a scope when
|
158
|
+
# using the console. This is useful when you want to see the queries of scopes
|
159
|
+
# instead of automatically returning the results.
|
160
|
+
# @return [Boolean] true to have scopes return query objects instead of results when
|
161
|
+
# running in the console.
|
162
|
+
|
163
|
+
# @!attribute field_formatter
|
154
164
|
# The method to use when converting field names to Parse column names. Default is {String#columnize}.
|
155
165
|
# By convention Parse uses lowercase-first camelcase syntax for field/column names, but ruby
|
156
166
|
# uses snakecase. To support this methodology we process all field constraints through the method
|
157
167
|
# defined by the field formatter. You may set this to nil to turn off this functionality.
|
158
168
|
# @return [Symbol] The filter method to process column and field names. Default {String#columnize}.
|
159
|
-
|
169
|
+
|
170
|
+
attr_accessor :field_formatter, :allow_scope_introspection
|
160
171
|
|
161
172
|
# @param str [String] the string to format
|
162
173
|
# @return [String] formatted string using {Parse::Query.field_formatter}.
|
@@ -196,6 +207,16 @@ module Parse
|
|
196
207
|
end
|
197
208
|
end
|
198
209
|
|
210
|
+
# Applies special singleton methods to a query instance in order to
|
211
|
+
# automatically fetch results when using any ruby console.
|
212
|
+
# @!visibility private
|
213
|
+
def apply_auto_introspection!(query)
|
214
|
+
unless @allow_scope_introspection
|
215
|
+
query.define_singleton_method(:to_s) { self.results.to_s }
|
216
|
+
query.define_singleton_method(:inspect) { self.results.to_a.inspect }
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
199
220
|
end
|
200
221
|
|
201
222
|
# @!attribute [r] client
|
@@ -269,7 +290,10 @@ module Parse
|
|
269
290
|
end # initialize
|
270
291
|
|
271
292
|
# Add a set of query expressions and constraints.
|
272
|
-
# @
|
293
|
+
# @example
|
294
|
+
# query.conditions({:field.gt => value})
|
295
|
+
# @param expressions [Hash] containing key value pairs of Parse::Operations
|
296
|
+
# and their value.
|
273
297
|
# @return [self]
|
274
298
|
def conditions(expressions = {})
|
275
299
|
expressions.each do |expression, value|
|
@@ -390,7 +414,7 @@ module Parse
|
|
390
414
|
# to get as many as 11_000 records with the aid if skipping.
|
391
415
|
# @return [self]
|
392
416
|
def limit(count)
|
393
|
-
if count == :max
|
417
|
+
if count == :max
|
394
418
|
@limit = 11_000
|
395
419
|
elsif count.is_a?(Numeric)
|
396
420
|
@limit = [ 0, count.to_i, 11_000].sort[1]
|
@@ -475,10 +499,19 @@ module Parse
|
|
475
499
|
self #chaining
|
476
500
|
end
|
477
501
|
|
478
|
-
# @
|
502
|
+
# @param raw [Boolean] whether to return the hash form of the constraints.
|
503
|
+
# @return [Array<Parse::Constraint>] if raw is false, an array of constraints
|
479
504
|
# composing the :where clause for this query.
|
480
|
-
|
481
|
-
|
505
|
+
# @return [Hash] if raw i strue, an hash representing the constraints.
|
506
|
+
def constraints(raw = false)
|
507
|
+
raw ? where_constraints : @where
|
508
|
+
end
|
509
|
+
|
510
|
+
# Formats the current set of Parse::Constraint instances in the where clause
|
511
|
+
# as an expression hash.
|
512
|
+
# @return [Hash] the set of constraints
|
513
|
+
def where_constraints
|
514
|
+
@where.reduce({}) { |memo, constraint| memo[constraint.operation] = constraint.value; memo }
|
482
515
|
end
|
483
516
|
|
484
517
|
# Add additional query constraints to the `where` clause. The `where` clause
|
@@ -527,17 +560,17 @@ module Parse
|
|
527
560
|
return self if where_clauses.blank?
|
528
561
|
# we can only have one compound query constraint. If we need to add another OR clause
|
529
562
|
# let's find the one we have (if any)
|
530
|
-
compound = @where.find { |f| f.is_a?(Parse::CompoundQueryConstraint) }
|
563
|
+
compound = @where.find { |f| f.is_a?(Parse::Constraint::CompoundQueryConstraint) }
|
531
564
|
# create a set of clauses that are not an OR clause.
|
532
|
-
remaining_clauses = @where.select { |f| f.is_a?(Parse::CompoundQueryConstraint) == false }
|
565
|
+
remaining_clauses = @where.select { |f| f.is_a?(Parse::Constraint::CompoundQueryConstraint) == false }
|
533
566
|
# if we don't have a OR clause to reuse, then create a new one with then
|
534
567
|
# current set of constraints
|
535
568
|
if compound.blank?
|
536
|
-
compound = Parse::CompoundQueryConstraint.new :or, [ Parse::Query.compile_where(remaining_clauses) ]
|
569
|
+
compound = Parse::Constraint::CompoundQueryConstraint.new :or, [ Parse::Query.compile_where(remaining_clauses) ]
|
537
570
|
end
|
538
571
|
# then take the where clauses from the second query and append them.
|
539
572
|
compound.value.push Parse::Query.compile_where(where_clauses)
|
540
|
-
#compound = Parse::CompoundQueryConstraint.new :or, [remaining_clauses, or_where_query.where]
|
573
|
+
#compound = Parse::Constraint::CompoundQueryConstraint.new :or, [remaining_clauses, or_where_query.where]
|
541
574
|
@where = [compound]
|
542
575
|
self #chaining
|
543
576
|
end
|
@@ -705,6 +738,19 @@ module Parse
|
|
705
738
|
end
|
706
739
|
alias_method :result, :results
|
707
740
|
|
741
|
+
# Similar to {#results} but takes an additional set of conditions to apply. This
|
742
|
+
# method helps support the use of class and instance level scopes.
|
743
|
+
# @param expressions (see #conditions)
|
744
|
+
# @yield (see #results)
|
745
|
+
# @return [Array<Hash>] if raw is set to true, a set of Parse JSON hashes.
|
746
|
+
# @return [Array<Parse::Object>] if raw is set to false, a list of matching Parse::Object subclasses.
|
747
|
+
# @see #results
|
748
|
+
def all(expressions = {limit: :max})
|
749
|
+
conditions(expressions)
|
750
|
+
return results(&Proc.new) if block_given?
|
751
|
+
results
|
752
|
+
end
|
753
|
+
|
708
754
|
# Builds objects based on the set of Parse JSON hashes in an array.
|
709
755
|
# @param list [Array<Hash>] a list of Parse JSON hashes
|
710
756
|
# @return [Array<Parse::Object>] an array of Parse::Object subclasses.
|
@@ -734,7 +780,7 @@ module Parse
|
|
734
780
|
def compile(encode: true, includeClassName: false)
|
735
781
|
run_callbacks :prepare do
|
736
782
|
q = {} #query
|
737
|
-
q[:limit] = 11_000 if @limit == :max
|
783
|
+
q[:limit] = 11_000 if @limit == :max
|
738
784
|
q[:limit] = @limit if @limit.is_a?(Numeric) && @limit > 0
|
739
785
|
q[:skip] = @skip if @skip > 0
|
740
786
|
|
@@ -12,6 +12,7 @@ module Parse
|
|
12
12
|
# be combined by merging different constraints (since they are multiple hashes)
|
13
13
|
# and some constraints may have higher precedence than others (ex. equality is higher
|
14
14
|
# precedence than an "in" query).
|
15
|
+
#
|
15
16
|
# All constraints should inherit from Parse::Constraint and should
|
16
17
|
# register their specific Operation method (ex. :eq or :lte)
|
17
18
|
# For more information about the query design pattern from DataMapper
|
@@ -102,8 +103,8 @@ module Parse
|
|
102
103
|
# @return [Object] a formatted value based on the data type.
|
103
104
|
def formatted_value(value)
|
104
105
|
d = value
|
105
|
-
d = { __type:
|
106
|
-
d = { __type:
|
106
|
+
d = { __type: Parse::Model::TYPE_DATE, iso: d.utc.iso8601(3) } if d.respond_to?(:utc)
|
107
|
+
d = { __type: Parse::Model::TYPE_DATE, iso: d.iso8601(3) } if d.respond_to?(:iso8601)
|
107
108
|
d = d.pointer if d.respond_to?(:pointer) #simplified query object
|
108
109
|
d = d.to_s if d.is_a?(Regexp)
|
109
110
|
#d = d.pointer if d.is_a?(Parse::Object) #simplified query object
|
@@ -162,6 +163,8 @@ module Parse
|
|
162
163
|
# Builds the JSON hash representation of this constraint for a Parse query.
|
163
164
|
# This method should be overriden by subclasses. The default implementation
|
164
165
|
# implements buildling the equality constraint.
|
166
|
+
# @raise ArgumentError if the constraint could be be build due to a bad parameter.
|
167
|
+
# This will be different depending on the constraint subclass.
|
165
168
|
# @return [Hash]
|
166
169
|
def build
|
167
170
|
return { @operation.operand => formatted_value } if @operation.operator == :eq || key.nil?
|
@@ -12,656 +12,655 @@ require_relative 'constraint'
|
|
12
12
|
# that inspired this, see http://datamapper.org/docs/find.html
|
13
13
|
|
14
14
|
module Parse
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
#
|
19
|
-
|
20
|
-
|
21
|
-
# q.where :field => Parse::Pointer("Field", "someObjectId")
|
22
|
-
# # alias, shorthand when we infer `:field` maps to `Field` parse class.
|
23
|
-
# q.where :field.id => "someObjectId"
|
24
|
-
# # "field":{"__type":"Pointer","className":"Field","objectId":"someObjectId"}}
|
25
|
-
#
|
26
|
-
# class Artist < Parse::Object
|
27
|
-
# end
|
28
|
-
#
|
29
|
-
# class Song < Parse::Object
|
30
|
-
# belongs_to :artist
|
31
|
-
# end
|
32
|
-
#
|
33
|
-
# artist = Artist.first # get any artist
|
34
|
-
# artist_id = artist.id # ex. artist.id
|
35
|
-
#
|
36
|
-
# # find all songs for this artist object
|
37
|
-
# Song.all :artist => artist
|
38
|
-
# In some cases, you do not have the Parse object, but you have its `objectId`.
|
39
|
-
# You can use the objectId in the query as follows:
|
40
|
-
#
|
41
|
-
# # shorthand if you are using convention. Will infer class `Artist`
|
42
|
-
# Song.all :artist.id => artist_id
|
43
|
-
#
|
44
|
-
# # other approaches, same result
|
45
|
-
# Song.all :artist => Artist.pointer(artist_id)
|
46
|
-
# Song.all :artist => Parse::Pointer.new("Artist", artist_id)
|
47
|
-
#
|
48
|
-
class ObjectIdConstraint < Constraint
|
49
|
-
# @!method id
|
50
|
-
# A registered method on a symbol to create the constraint.
|
51
|
-
# @example
|
15
|
+
class Constraint
|
16
|
+
# A constraint for matching by a specific objectId value.
|
17
|
+
#
|
18
|
+
# # where this Parse object equals the object in the column `field`.
|
19
|
+
# q.where :field => Parse::Pointer("Field", "someObjectId")
|
20
|
+
# # alias, shorthand when we infer `:field` maps to `Field` parse class.
|
52
21
|
# q.where :field.id => "someObjectId"
|
53
|
-
#
|
54
|
-
|
55
|
-
|
56
|
-
#
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
22
|
+
# # "field":{"__type":"Pointer","className":"Field","objectId":"someObjectId"}}
|
23
|
+
#
|
24
|
+
# class Artist < Parse::Object
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# class Song < Parse::Object
|
28
|
+
# belongs_to :artist
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# artist = Artist.first # get any artist
|
32
|
+
# artist_id = artist.id # ex. artist.id
|
33
|
+
#
|
34
|
+
# # find all songs for this artist object
|
35
|
+
# Song.all :artist => artist
|
36
|
+
# In some cases, you do not have the Parse object, but you have its `objectId`.
|
37
|
+
# You can use the objectId in the query as follows:
|
38
|
+
#
|
39
|
+
# # shorthand if you are using convention. Will infer class `Artist`
|
40
|
+
# Song.all :artist.id => artist_id
|
41
|
+
#
|
42
|
+
# # other approaches, same result
|
43
|
+
# Song.all :artist => Artist.pointer(artist_id)
|
44
|
+
# Song.all :artist => Parse::Pointer.new("Artist", artist_id)
|
45
|
+
#
|
46
|
+
class ObjectIdConstraint < Constraint
|
47
|
+
# @!method id
|
48
|
+
# A registered method on a symbol to create the constraint.
|
49
|
+
# @example
|
50
|
+
# q.where :field.id => "someObjectId"
|
51
|
+
# @return [ObjectIdConstraint]
|
52
|
+
register :id
|
53
|
+
|
54
|
+
# @return [Hash] the compiled constraint.
|
55
|
+
def build
|
56
|
+
className = operand.to_parse_class
|
57
|
+
value = formatted_value
|
58
|
+
begin
|
59
|
+
klass = className.constantize
|
60
|
+
rescue NameError => e
|
61
|
+
klass = Parse::Model.find_class className
|
62
|
+
end
|
65
63
|
|
66
|
-
|
67
|
-
|
68
|
-
|
64
|
+
unless klass.present? && klass.is_a?(Parse::Object) == false
|
65
|
+
raise ArgumentError, "#{self.class}: No Parse class defined for #{operand} as '#{className}'"
|
66
|
+
end
|
69
67
|
|
70
|
-
|
71
|
-
|
68
|
+
# allow symbols
|
69
|
+
value = value.to_s if value.is_a?(Symbol)
|
72
70
|
|
73
|
-
|
74
|
-
|
71
|
+
unless value.is_a?(String) && value.strip.present?
|
72
|
+
raise ArgumentError, "#{self.class}: value must be of string type representing a Parse object id."
|
73
|
+
end
|
74
|
+
value.strip!
|
75
|
+
return { @operation.operand => klass.pointer(value) }
|
75
76
|
end
|
76
|
-
|
77
|
-
return { @operation.operand => klass.pointer(value) }
|
77
|
+
|
78
78
|
end
|
79
79
|
|
80
|
-
|
80
|
+
# Equivalent to the `$or` Parse query operation. This is useful if you want to
|
81
|
+
# find objects that match several queries. We overload the `|` operator in
|
82
|
+
# order to have a clean syntax for joining these `or` operations.
|
83
|
+
# or_query = query1 | query2 | query3
|
84
|
+
# query = Player.where(:wins.gt => 150) | Player.where(:wins.lt => 5)
|
85
|
+
#
|
86
|
+
# query.or_where :field => value
|
87
|
+
#
|
88
|
+
class CompoundQueryConstraint < Constraint
|
89
|
+
contraint_keyword :$or
|
90
|
+
register :or
|
91
|
+
|
92
|
+
# @return [Hash] the compiled constraint.
|
93
|
+
def build
|
94
|
+
or_clauses = formatted_value
|
95
|
+
return { :$or => Array.wrap(or_clauses) }
|
96
|
+
end
|
81
97
|
|
82
|
-
# Equivalent to the `$or` Parse query operation. This is useful if you want to
|
83
|
-
# find objects that match several queries. We overload the `|` operator in
|
84
|
-
# order to have a clean syntax for joining these `or` operations.
|
85
|
-
# or_query = query1 | query2 | query3
|
86
|
-
# query = Player.where(:wins.gt => 150) | Player.where(:wins.lt => 5)
|
87
|
-
#
|
88
|
-
# query.or_where :field => value
|
89
|
-
#
|
90
|
-
class CompoundQueryConstraint < Constraint
|
91
|
-
contraint_keyword :$or
|
92
|
-
register :or
|
93
|
-
|
94
|
-
# @return [Hash] the compiled constraint.
|
95
|
-
def build
|
96
|
-
or_clauses = formatted_value
|
97
|
-
return { :$or => Array.wrap(or_clauses) }
|
98
98
|
end
|
99
99
|
|
100
|
-
|
101
|
-
|
102
|
-
# Equivalent to the `$lte` Parse query operation. The alias `on_or_before` is provided for readability.
|
103
|
-
# q.where :field.lte => value
|
104
|
-
# q.where :field.on_or_before => date
|
105
|
-
#
|
106
|
-
# q.where :created_at.on_or_before => DateTime.now
|
107
|
-
# @see LessThanConstraint
|
108
|
-
class LessThanOrEqualConstraint < Constraint
|
109
|
-
# @!method lte
|
110
|
-
# A registered method on a symbol to create the constraint. Maps to Parse operator "$lte".
|
111
|
-
# @example
|
100
|
+
# Equivalent to the `$lte` Parse query operation. The alias `on_or_before` is provided for readability.
|
112
101
|
# q.where :field.lte => value
|
113
|
-
#
|
114
|
-
|
115
|
-
#
|
116
|
-
#
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
102
|
+
# q.where :field.on_or_before => date
|
103
|
+
#
|
104
|
+
# q.where :created_at.on_or_before => DateTime.now
|
105
|
+
# @see LessThanConstraint
|
106
|
+
class LessThanOrEqualConstraint < Constraint
|
107
|
+
# @!method lte
|
108
|
+
# A registered method on a symbol to create the constraint. Maps to Parse operator "$lte".
|
109
|
+
# @example
|
110
|
+
# q.where :field.lte => value
|
111
|
+
# @return [LessThanOrEqualConstraint]
|
112
|
+
|
113
|
+
# @!method less_than_or_equal
|
114
|
+
# Alias for {lte}
|
115
|
+
# @return [LessThanOrEqualConstraint]
|
116
|
+
|
117
|
+
# @!method on_or_before
|
118
|
+
# Alias for {lte} that provides better readability when constraining dates.
|
119
|
+
# @return [LessThanOrEqualConstraint]
|
120
|
+
contraint_keyword :$lte
|
121
|
+
register :lte
|
122
|
+
register :less_than_or_equal
|
123
|
+
register :on_or_before
|
124
|
+
end
|
127
125
|
|
128
|
-
|
129
|
-
# q.where :field.lt => value
|
130
|
-
# q.where :field.before => date
|
131
|
-
#
|
132
|
-
# q.where :created_at.before => DateTime.now
|
133
|
-
class LessThanConstraint < Constraint
|
134
|
-
# @!method lt
|
135
|
-
# A registered method on a symbol to create the constraint. Maps to Parse operator "$lt".
|
136
|
-
# @example
|
126
|
+
# Equivalent to the `$lt` Parse query operation. The alias `before` is provided for readability.
|
137
127
|
# q.where :field.lt => value
|
138
|
-
#
|
139
|
-
|
140
|
-
#
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
#
|
161
|
-
# @example
|
128
|
+
# q.where :field.before => date
|
129
|
+
#
|
130
|
+
# q.where :created_at.before => DateTime.now
|
131
|
+
class LessThanConstraint < Constraint
|
132
|
+
# @!method lt
|
133
|
+
# A registered method on a symbol to create the constraint. Maps to Parse operator "$lt".
|
134
|
+
# @example
|
135
|
+
# q.where :field.lt => value
|
136
|
+
# @return [LessThanConstraint]
|
137
|
+
|
138
|
+
# @!method less_than
|
139
|
+
# # Alias for {lt}.
|
140
|
+
# @return [LessThanConstraint]
|
141
|
+
|
142
|
+
# @!method before
|
143
|
+
# Alias for {lt} that provides better readability when constraining dates.
|
144
|
+
# @return [LessThanConstraint]
|
145
|
+
contraint_keyword :$lt
|
146
|
+
register :lt
|
147
|
+
register :less_than
|
148
|
+
register :before
|
149
|
+
end
|
150
|
+
# Equivalent to the `$gt` Parse query operation. The alias `after` is provided for readability.
|
162
151
|
# q.where :field.gt => value
|
163
|
-
#
|
164
|
-
|
165
|
-
#
|
166
|
-
#
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
152
|
+
# q.where :field.after => date
|
153
|
+
#
|
154
|
+
# q.where :created_at.after => DateTime.now
|
155
|
+
# @see GreaterThanOrEqualConstraint
|
156
|
+
class GreaterThanConstraint < Constraint
|
157
|
+
# @!method gt
|
158
|
+
# A registered method on a symbol to create the constraint. Maps to Parse operator "$gt".
|
159
|
+
# @example
|
160
|
+
# q.where :field.gt => value
|
161
|
+
# @return [GreaterThanConstraint]
|
162
|
+
|
163
|
+
# @!method greater_than
|
164
|
+
# # Alias for {gt}.
|
165
|
+
# @return [GreaterThanConstraint]
|
166
|
+
|
167
|
+
# @!method after
|
168
|
+
# Alias for {gt} that provides better readability when constraining dates.
|
169
|
+
# @return [GreaterThanConstraint]
|
170
|
+
contraint_keyword :$gt
|
171
|
+
register :gt
|
172
|
+
register :greater_than
|
173
|
+
register :after
|
174
|
+
end
|
177
175
|
|
178
|
-
|
179
|
-
# q.where :field.gte => value
|
180
|
-
# q.where :field.on_or_after => date
|
181
|
-
#
|
182
|
-
# q.where :created_at.on_or_after => DateTime.now
|
183
|
-
# @see GreaterThanConstraint
|
184
|
-
class GreaterThanOrEqualConstraint < Constraint
|
185
|
-
# @!method gte
|
186
|
-
# A registered method on a symbol to create the constraint. Maps to Parse operator "$gte".
|
187
|
-
# @example
|
176
|
+
# Equivalent to the `$gte` Parse query operation. The alias `on_or_after` is provided for readability.
|
188
177
|
# q.where :field.gte => value
|
189
|
-
#
|
190
|
-
|
191
|
-
#
|
192
|
-
#
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
178
|
+
# q.where :field.on_or_after => date
|
179
|
+
#
|
180
|
+
# q.where :created_at.on_or_after => DateTime.now
|
181
|
+
# @see GreaterThanConstraint
|
182
|
+
class GreaterThanOrEqualConstraint < Constraint
|
183
|
+
# @!method gte
|
184
|
+
# A registered method on a symbol to create the constraint. Maps to Parse operator "$gte".
|
185
|
+
# @example
|
186
|
+
# q.where :field.gte => value
|
187
|
+
# @return [GreaterThanOrEqualConstraint]
|
188
|
+
|
189
|
+
# @!method greater_than_or_equal
|
190
|
+
# # Alias for {gte}.
|
191
|
+
# @return [GreaterThanOrEqualConstraint]
|
192
|
+
|
193
|
+
# @!method on_or_after
|
194
|
+
# Alias for {gte} that provides better readability when constraining dates.
|
195
|
+
# @return [GreaterThanOrEqualConstraint]
|
196
|
+
contraint_keyword :$gte
|
197
|
+
register :gte
|
198
|
+
register :greater_than_or_equal
|
199
|
+
register :on_or_after
|
200
|
+
end
|
203
201
|
|
204
|
-
|
205
|
-
# q.where :field.not => value
|
206
|
-
class NotEqualConstraint < Constraint
|
207
|
-
# @!method not
|
208
|
-
# A registered method on a symbol to create the constraint. Maps to Parse operator "$ne".
|
209
|
-
# @example
|
202
|
+
# Equivalent to the `$ne` Parse query operation. Where a particular field is not equal to value.
|
210
203
|
# q.where :field.not => value
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
204
|
+
class NotEqualConstraint < Constraint
|
205
|
+
# @!method not
|
206
|
+
# A registered method on a symbol to create the constraint. Maps to Parse operator "$ne".
|
207
|
+
# @example
|
208
|
+
# q.where :field.not => value
|
209
|
+
# @return [NotEqualConstraint]
|
210
|
+
|
211
|
+
# @!method ne
|
212
|
+
# # Alias for {not}.
|
213
|
+
# @return [NotEqualConstraint]
|
214
|
+
contraint_keyword :$ne
|
215
|
+
register :not
|
216
|
+
register :ne
|
217
|
+
end
|
220
218
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
219
|
+
# Provides a mechanism using the equality operator to check for `(undefined)` values.
|
220
|
+
# Nullabiliity constraint maps the `$exists` Parse clause to enable checking for
|
221
|
+
# existance in a column when performing geoqueries due to a Parse limitation.
|
222
|
+
# q.where :field.null => false
|
223
|
+
# @note Parse currently has a bug that if you select items near a location
|
224
|
+
# and want to make sure a different column has a value, you need to
|
225
|
+
# search where the column does not contanin a null/undefined value.
|
226
|
+
# Therefore we override the build method to change the operation to a
|
227
|
+
# {NotEqualConstraint}.
|
228
|
+
# @see ExistsConstraint
|
229
|
+
class NullabilityConstraint < Constraint
|
230
|
+
# @!method null
|
231
|
+
# A registered method on a symbol to create the constraint.
|
232
|
+
# @example
|
233
|
+
# q.where :field.null => true
|
234
|
+
# @return [NullabilityConstraint]
|
235
|
+
contraint_keyword :$exists
|
236
|
+
register :null
|
237
|
+
|
238
|
+
# @return [Hash] the compiled constraint.
|
239
|
+
def build
|
240
|
+
# if nullability is equal true, then $exists should be set to false
|
241
|
+
|
242
|
+
value = formatted_value
|
243
|
+
unless value == true || value == false
|
244
|
+
raise ArgumentError, "#{self.class}: Non-Boolean value passed, it must be either `true` or `false`"
|
245
|
+
end
|
248
246
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
247
|
+
if value == true
|
248
|
+
return { @operation.operand => { key => false} }
|
249
|
+
else
|
250
|
+
#current bug in parse where if you want exists => true with geo queries
|
251
|
+
# we should map it to a "not equal to null" constraint
|
252
|
+
return { @operation.operand => { Parse::Constraint::NotEqualConstraint.key => nil } }
|
253
|
+
end
|
256
254
|
|
255
|
+
end
|
257
256
|
end
|
258
|
-
end
|
259
257
|
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
# q.where :field.exists => true
|
264
|
-
#
|
265
|
-
# @see NullabilityConstraint
|
266
|
-
class ExistsConstraint < Constraint
|
267
|
-
# @!method exists
|
268
|
-
# A registered method on a symbol to create the constraint. Maps to Parse operator "$exists".
|
269
|
-
# @example
|
258
|
+
# Equivalent to the `#exists` Parse query operation. Checks whether a value is
|
259
|
+
# set for key. The difference between this operation and the nullability check
|
260
|
+
# is when using compound queries with location.
|
270
261
|
# q.where :field.exists => true
|
271
|
-
#
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
#
|
278
|
-
|
262
|
+
#
|
263
|
+
# @see NullabilityConstraint
|
264
|
+
class ExistsConstraint < Constraint
|
265
|
+
# @!method exists
|
266
|
+
# A registered method on a symbol to create the constraint. Maps to Parse operator "$exists".
|
267
|
+
# @example
|
268
|
+
# q.where :field.exists => true
|
269
|
+
# @return [ExistsConstraint]
|
270
|
+
contraint_keyword :$exists
|
271
|
+
register :exists
|
272
|
+
|
273
|
+
# @return [Hash] the compiled constraint.
|
274
|
+
def build
|
275
|
+
# if nullability is equal true, then $exists should be set to false
|
276
|
+
value = formatted_value
|
277
|
+
|
278
|
+
unless value == true || value == false
|
279
|
+
raise ArgumentError, "#{self.class}: Non-Boolean value passed, it must be either `true` or `false`"
|
280
|
+
end
|
279
281
|
|
280
|
-
|
281
|
-
raise ConstraintError, "#{self.class}: Non-Boolean value passed, it must be either `true` or `false`"
|
282
|
+
return { @operation.operand => { key => value } }
|
282
283
|
end
|
283
|
-
|
284
|
-
return { @operation.operand => { key => value } }
|
285
284
|
end
|
286
|
-
end
|
287
285
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
# q.where :field.in => array
|
293
|
-
# q.where :score.in => [1,3,5,7,9]
|
294
|
-
#
|
295
|
-
# @see ContainsAllConstraint
|
296
|
-
# @see NotContainedInConstraint
|
297
|
-
class ContainedInConstraint < Constraint
|
298
|
-
# @!method in
|
299
|
-
# A registered method on a symbol to create the constraint. Maps to Parse operator "$in".
|
300
|
-
# @example
|
286
|
+
# Equivalent to the `$in` Parse query operation. Checks whether the value in the
|
287
|
+
# column field is contained in the set of values in the target array. If the
|
288
|
+
# field is an array data type, it checks whether at least one value in the
|
289
|
+
# field array is contained in the set of values in the target array.
|
301
290
|
# q.where :field.in => array
|
302
|
-
#
|
303
|
-
|
304
|
-
#
|
305
|
-
#
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
291
|
+
# q.where :score.in => [1,3,5,7,9]
|
292
|
+
#
|
293
|
+
# @see ContainsAllConstraint
|
294
|
+
# @see NotContainedInConstraint
|
295
|
+
class ContainedInConstraint < Constraint
|
296
|
+
# @!method in
|
297
|
+
# A registered method on a symbol to create the constraint. Maps to Parse operator "$in".
|
298
|
+
# @example
|
299
|
+
# q.where :field.in => array
|
300
|
+
# @return [ContainedInConstraint]
|
301
|
+
|
302
|
+
# @!method contained_in
|
303
|
+
# Alias for {in}
|
304
|
+
# @return [ContainedInConstraint]
|
305
|
+
contraint_keyword :$in
|
306
|
+
register :in
|
307
|
+
register :contained_in
|
308
|
+
|
309
|
+
# @return [Hash] the compiled constraint.
|
310
|
+
def build
|
311
|
+
val = formatted_value
|
312
|
+
val = [val].compact unless val.is_a?(Array)
|
313
|
+
{ @operation.operand => { key => val } }
|
314
|
+
end
|
317
315
|
|
318
|
-
|
316
|
+
end
|
319
317
|
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
# q.where :field.not_in => array
|
327
|
-
# q.where :player_name.not_in => ["Jonathan", "Dario", "Shawn"]
|
328
|
-
# @see ContainedInConstraint
|
329
|
-
# @see ContainsAllConstraint
|
330
|
-
class NotContainedInConstraint < Constraint
|
331
|
-
# @!method not_in
|
332
|
-
# A registered method on a symbol to create the constraint. Maps to Parse operator "$nin".
|
333
|
-
# @example
|
318
|
+
# Equivalent to the `$nin` Parse query operation. Checks whether the value in
|
319
|
+
# the column field is *not* contained in the set of values in the target
|
320
|
+
# array. If the field is an array data type, it checks whether at least one
|
321
|
+
# value in the field array is *not* contained in the set of values in the
|
322
|
+
# target array.
|
323
|
+
#
|
334
324
|
# q.where :field.not_in => array
|
335
|
-
#
|
336
|
-
|
337
|
-
#
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
325
|
+
# q.where :player_name.not_in => ["Jonathan", "Dario", "Shawn"]
|
326
|
+
# @see ContainedInConstraint
|
327
|
+
# @see ContainsAllConstraint
|
328
|
+
class NotContainedInConstraint < Constraint
|
329
|
+
# @!method not_in
|
330
|
+
# A registered method on a symbol to create the constraint. Maps to Parse operator "$nin".
|
331
|
+
# @example
|
332
|
+
# q.where :field.not_in => array
|
333
|
+
# @return [NotContainedInConstraint]
|
334
|
+
|
335
|
+
# @!method nin
|
336
|
+
# Alias for {not_in}
|
337
|
+
# @return [NotContainedInConstraint]
|
338
|
+
|
339
|
+
# @!method not_contained_in
|
340
|
+
# Alias for {not_in}
|
341
|
+
# @return [NotContainedInConstraint]
|
342
|
+
contraint_keyword :$nin
|
343
|
+
register :not_in
|
344
|
+
register :nin
|
345
|
+
register :not_contained_in
|
346
|
+
|
347
|
+
# @return [Hash] the compiled constraint.
|
348
|
+
def build
|
349
|
+
val = formatted_value
|
350
|
+
val = [val].compact unless val.is_a?(Array)
|
351
|
+
{ @operation.operand => { key => val } }
|
352
|
+
end
|
355
353
|
|
356
|
-
|
354
|
+
end
|
357
355
|
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
# q.where :field.all => array
|
363
|
-
# q.where :array_key.all => [2,3,4]
|
364
|
-
#
|
365
|
-
# @see ContainedInConstraint
|
366
|
-
# @see NotContainedInConstraint
|
367
|
-
class ContainsAllConstraint < Constraint
|
368
|
-
# @!method all
|
369
|
-
# A registered method on a symbol to create the constraint. Maps to Parse operator "$all".
|
370
|
-
# @example
|
356
|
+
# Equivalent to the $all Parse query operation. Checks whether the value in
|
357
|
+
# the column field contains all of the given values provided in the array. Note
|
358
|
+
# that the field column should be of type {Array} in your Parse class.
|
359
|
+
#
|
371
360
|
# q.where :field.all => array
|
372
|
-
#
|
373
|
-
|
374
|
-
#
|
375
|
-
#
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
361
|
+
# q.where :array_key.all => [2,3,4]
|
362
|
+
#
|
363
|
+
# @see ContainedInConstraint
|
364
|
+
# @see NotContainedInConstraint
|
365
|
+
class ContainsAllConstraint < Constraint
|
366
|
+
# @!method all
|
367
|
+
# A registered method on a symbol to create the constraint. Maps to Parse operator "$all".
|
368
|
+
# @example
|
369
|
+
# q.where :field.all => array
|
370
|
+
# @return [ContainsAllConstraint]
|
371
|
+
|
372
|
+
# @!method contains_all
|
373
|
+
# Alias for {all}
|
374
|
+
# @return [ContainsAllConstraint]
|
375
|
+
contraint_keyword :$all
|
376
|
+
register :all
|
377
|
+
register :contains_all
|
378
|
+
|
379
|
+
# @return [Hash] the compiled constraint.
|
380
|
+
def build
|
381
|
+
val = formatted_value
|
382
|
+
val = [val].compact unless val.is_a?(Array)
|
383
|
+
{ @operation.operand => { key => val } }
|
384
|
+
end
|
386
385
|
end
|
387
|
-
end
|
388
386
|
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
387
|
+
# Equivalent to the `$select` Parse query operation. This matches a value for a
|
388
|
+
# key in the result of a different query.
|
389
|
+
# q.where :field.select => { key: "field", query: query }
|
390
|
+
#
|
391
|
+
# # example
|
392
|
+
# value = { key: 'city', query: Artist.where(:fan_count.gt => 50) }
|
393
|
+
# q.where :hometown.select => value
|
394
|
+
#
|
395
|
+
# # if the local field is the same name as the foreign table field, you can omit hash
|
396
|
+
# # assumes key: 'city'
|
397
|
+
# q.where :city.select => Artist.where(:fan_count.gt => 50)
|
398
|
+
#
|
399
|
+
class SelectionConstraint < Constraint
|
400
|
+
# @!method select
|
401
|
+
# A registered method on a symbol to create the constraint. Maps to Parse operator "$select".
|
402
|
+
# @return [SelectionConstraint]
|
403
|
+
contraint_keyword :$select
|
404
|
+
register :select
|
405
|
+
|
406
|
+
# @return [Hash] the compiled constraint.
|
407
|
+
def build
|
408
|
+
|
409
|
+
# if it's a hash, then it should be {:key=>"objectId", :query=>[]}
|
410
|
+
remote_field_name = @operation.operand
|
411
|
+
query = nil
|
412
|
+
if @value.is_a?(Hash)
|
413
|
+
res = @value.symbolize_keys
|
414
|
+
remote_field_name = res[:key] || remote_field_name
|
415
|
+
query = res[:query]
|
416
|
+
unless query.is_a?(Parse::Query)
|
417
|
+
raise ArgumentError, "Invalid Parse::Query object provided in :query field of value: #{@operation.operand}.#{$dontSelect} => #{@value}"
|
418
|
+
end
|
419
|
+
query = query.compile(encode: false, includeClassName: true)
|
420
|
+
elsif @value.is_a?(Parse::Query)
|
421
|
+
# if its a query, then assume dontSelect key is the same name as operand.
|
422
|
+
query = @value.compile(encode: false, includeClassName: true)
|
423
|
+
else
|
424
|
+
raise ArgumentError, "Invalid `:select` query constraint. It should follow the format: :field.select => { key: 'key', query: '<Parse::Query>' }"
|
420
425
|
end
|
421
|
-
|
422
|
-
elsif @value.is_a?(Parse::Query)
|
423
|
-
# if its a query, then assume dontSelect key is the same name as operand.
|
424
|
-
query = @value.compile(encode: false, includeClassName: true)
|
425
|
-
else
|
426
|
-
raise ConstraintError, "Invalid `:select` query constraint. It should follow the format: :field.select => { key: 'key', query: '<Parse::Query>' }"
|
426
|
+
{ @operation.operand => { :$select => { key: remote_field_name, query: query } } }
|
427
427
|
end
|
428
|
-
{ @operation.operand => { :$select => { key: remote_field_name, query: query } } }
|
429
428
|
end
|
430
|
-
end
|
431
429
|
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
# q.where :field.reject => { key: :other_field, query: query }
|
436
|
-
#
|
437
|
-
# value = { key: 'city', query: Artist.where(:fan_count.gt => 50) }
|
438
|
-
# q.where :hometown.reject => value
|
439
|
-
#
|
440
|
-
# # if the local field is the same name as the foreign table field, you can omit hash
|
441
|
-
# # assumes key: 'city'
|
442
|
-
# q.where :city.reject => Artist.where(:fan_count.gt => 50)
|
443
|
-
#
|
444
|
-
# @see SelectionConstraint
|
445
|
-
class RejectionConstraint < Constraint
|
446
|
-
|
447
|
-
# @!method dont_select
|
448
|
-
# A registered method on a symbol to create the constraint. Maps to Parse operator "$dontSelect".
|
449
|
-
# @example
|
430
|
+
# Equivalent to the `$dontSelect` Parse query operation. Requires that a field's
|
431
|
+
# value not match a value for a key in the result of a different query.
|
432
|
+
#
|
450
433
|
# q.where :field.reject => { key: :other_field, query: query }
|
451
|
-
#
|
452
|
-
|
453
|
-
#
|
454
|
-
#
|
455
|
-
#
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
#
|
464
|
-
|
465
|
-
query
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
434
|
+
#
|
435
|
+
# value = { key: 'city', query: Artist.where(:fan_count.gt => 50) }
|
436
|
+
# q.where :hometown.reject => value
|
437
|
+
#
|
438
|
+
# # if the local field is the same name as the foreign table field, you can omit hash
|
439
|
+
# # assumes key: 'city'
|
440
|
+
# q.where :city.reject => Artist.where(:fan_count.gt => 50)
|
441
|
+
#
|
442
|
+
# @see SelectionConstraint
|
443
|
+
class RejectionConstraint < Constraint
|
444
|
+
|
445
|
+
# @!method dont_select
|
446
|
+
# A registered method on a symbol to create the constraint. Maps to Parse operator "$dontSelect".
|
447
|
+
# @example
|
448
|
+
# q.where :field.reject => { key: :other_field, query: query }
|
449
|
+
# @return [RejectionConstraint]
|
450
|
+
|
451
|
+
# @!method reject
|
452
|
+
# Alias for {dont_select}
|
453
|
+
# @return [RejectionConstraint]
|
454
|
+
contraint_keyword :$dontSelect
|
455
|
+
register :reject
|
456
|
+
register :dont_select
|
457
|
+
|
458
|
+
# @return [Hash] the compiled constraint.
|
459
|
+
def build
|
460
|
+
|
461
|
+
# if it's a hash, then it should be {:key=>"objectId", :query=>[]}
|
462
|
+
remote_field_name = @operation.operand
|
463
|
+
query = nil
|
464
|
+
if @value.is_a?(Hash)
|
465
|
+
res = @value.symbolize_keys
|
466
|
+
remote_field_name = res[:key] || remote_field_name
|
467
|
+
query = res[:query]
|
468
|
+
unless query.is_a?(Parse::Query)
|
469
|
+
raise ArgumentError, "Invalid Parse::Query object provided in :query field of value: #{@operation.operand}.#{$dontSelect} => #{@value}"
|
470
|
+
end
|
471
|
+
query = query.compile(encode: false, includeClassName: true)
|
472
|
+
elsif @value.is_a?(Parse::Query)
|
473
|
+
# if its a query, then assume dontSelect key is the same name as operand.
|
474
|
+
query = @value.compile(encode: false, includeClassName: true)
|
475
|
+
else
|
476
|
+
raise ArgumentError, "Invalid `:reject` query constraint. It should follow the format: :field.reject => { key: 'key', query: '<Parse::Query>' }"
|
472
477
|
end
|
473
|
-
|
474
|
-
elsif @value.is_a?(Parse::Query)
|
475
|
-
# if its a query, then assume dontSelect key is the same name as operand.
|
476
|
-
query = @value.compile(encode: false, includeClassName: true)
|
477
|
-
else
|
478
|
-
raise ConstraintError, "Invalid `:reject` query constraint. It should follow the format: :field.reject => { key: 'key', query: '<Parse::Query>' }"
|
478
|
+
{ @operation.operand => { :$dontSelect => { key: remote_field_name, query: query } } }
|
479
479
|
end
|
480
|
-
{ @operation.operand => { :$dontSelect => { key: remote_field_name, query: query } } }
|
481
480
|
end
|
482
|
-
end
|
483
481
|
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
# q.where :field.like => /ruby_regex/i
|
488
|
-
# :name.like => /Bob/i
|
489
|
-
#
|
490
|
-
class RegularExpressionConstraint < Constraint
|
491
|
-
#Requires that a key's value match a regular expression
|
492
|
-
|
493
|
-
# @!method like
|
494
|
-
# A registered method on a symbol to create the constraint. Maps to Parse operator "$regex".
|
495
|
-
# @example
|
482
|
+
# Equivalent to the `$regex` Parse query operation. Requires that a field value
|
483
|
+
# match a regular expression.
|
484
|
+
#
|
496
485
|
# q.where :field.like => /ruby_regex/i
|
497
|
-
#
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
486
|
+
# :name.like => /Bob/i
|
487
|
+
#
|
488
|
+
class RegularExpressionConstraint < Constraint
|
489
|
+
#Requires that a key's value match a regular expression
|
490
|
+
|
491
|
+
# @!method like
|
492
|
+
# A registered method on a symbol to create the constraint. Maps to Parse operator "$regex".
|
493
|
+
# @example
|
494
|
+
# q.where :field.like => /ruby_regex/i
|
495
|
+
# @return [RegularExpressionConstraint]
|
496
|
+
|
497
|
+
# @!method regex
|
498
|
+
# Alias for {like}
|
499
|
+
# @return [RegularExpressionConstraint]
|
500
|
+
contraint_keyword :$regex
|
501
|
+
register :like
|
502
|
+
register :regex
|
503
|
+
end
|
506
504
|
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
505
|
+
# Equivalent to the `$relatedTo` Parse query operation. If you want to
|
506
|
+
# retrieve objects that are members of a `Relation` field in your Parse class.
|
507
|
+
#
|
508
|
+
# q.where :field.related_to => pointer
|
509
|
+
#
|
510
|
+
# # find all Users who have liked this post object
|
511
|
+
# post = Post.first
|
512
|
+
# users = Parse::User.all :likes.related_to => post
|
513
|
+
#
|
514
|
+
class RelationQueryConstraint < Constraint
|
515
|
+
# @!method related_to
|
516
|
+
# A registered method on a symbol to create the constraint. Maps to Parse operator "$relatedTo".
|
517
|
+
# @example
|
518
|
+
# q.where :field.related_to => pointer
|
519
|
+
# @return [RelationQueryConstraint]
|
520
|
+
|
521
|
+
# @!method rel
|
522
|
+
# Alias for {related_to}
|
523
|
+
# @return [RelationQueryConstraint]
|
524
|
+
contraint_keyword :$relatedTo
|
525
|
+
register :related_to
|
526
|
+
register :rel
|
527
|
+
|
528
|
+
# @return [Hash] the compiled constraint.
|
529
|
+
def build
|
530
|
+
# pointer = formatted_value
|
531
|
+
# unless pointer.is_a?(Parse::Pointer)
|
532
|
+
# raise "Invalid Parse::Pointer passed to :related(#{@operation.operand}) constraint : #{pointer}"
|
533
|
+
# end
|
534
|
+
{ :$relatedTo => { object: formatted_value, key: @operation.operand } }
|
535
|
+
end
|
537
536
|
end
|
538
|
-
end
|
539
537
|
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
# q.where :field.matches => query
|
544
|
-
# # assume Post class has an image column.
|
545
|
-
# q.where :post.matches => Post.where(:image.exists => true )
|
546
|
-
#
|
547
|
-
class InQueryConstraint < Constraint
|
548
|
-
# @!method matches
|
549
|
-
# A registered method on a symbol to create the constraint. Maps to Parse operator "$inQuery".
|
550
|
-
# @example
|
538
|
+
# Equivalent to the `$inQuery` Parse query operation. Useful if you want to
|
539
|
+
# retrieve objects where a field contains an object that matches another query.
|
540
|
+
#
|
551
541
|
# q.where :field.matches => query
|
552
|
-
#
|
553
|
-
|
554
|
-
#
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
542
|
+
# # assume Post class has an image column.
|
543
|
+
# q.where :post.matches => Post.where(:image.exists => true )
|
544
|
+
#
|
545
|
+
class InQueryConstraint < Constraint
|
546
|
+
# @!method matches
|
547
|
+
# A registered method on a symbol to create the constraint. Maps to Parse operator "$inQuery".
|
548
|
+
# @example
|
549
|
+
# q.where :field.matches => query
|
550
|
+
# @return [InQueryConstraint]
|
551
|
+
|
552
|
+
# @!method in_query
|
553
|
+
# Alias for {matches}
|
554
|
+
# @return [InQueryConstraint]
|
555
|
+
contraint_keyword :$inQuery
|
556
|
+
register :matches
|
557
|
+
register :in_query
|
558
|
+
end
|
561
559
|
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
560
|
+
# Equivalent to the `$notInQuery` Parse query operation. Useful if you want to
|
561
|
+
# retrieve objects where a field contains an object that does not match another query.
|
562
|
+
# This is the inverse of the {InQueryConstraint}.
|
563
|
+
#
|
564
|
+
# q.where :field.excludes => query
|
565
|
+
#
|
566
|
+
# q.where :post.excludes => Post.where(:image.exists => true
|
567
|
+
#
|
568
|
+
class NotInQueryConstraint < Constraint
|
569
|
+
# @!method excludes
|
570
|
+
# A registered method on a symbol to create the constraint. Maps to Parse operator "$notInQuery".
|
571
|
+
# @example
|
572
|
+
# q.where :field.excludes => query
|
573
|
+
# @return [NotInQueryConstraint]
|
574
|
+
|
575
|
+
# @!method not_in_query
|
576
|
+
# Alias for {excludes}
|
577
|
+
# @return [NotInQueryConstraint]
|
578
|
+
contraint_keyword :$notInQuery
|
579
|
+
register :excludes
|
580
|
+
register :not_in_query
|
583
581
|
|
584
|
-
|
582
|
+
end
|
585
583
|
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
# q.where :field.near => geopoint
|
591
|
-
#
|
592
|
-
# geopoint = Parse::GeoPoint.new(30.0, -20.0)
|
593
|
-
# PlaceObject.all :location.near => geopoint
|
594
|
-
# If you wish to constrain the geospatial query to a maximum number of _miles_,
|
595
|
-
# you can utilize the `max_miles` method on a `Parse::GeoPoint` object. This
|
596
|
-
# is equivalent to the `$maxDistanceInMiles` constraint used with `$nearSphere`.
|
597
|
-
#
|
598
|
-
# q.where :field.near => geopoint.max_miles(distance)
|
599
|
-
# # or provide a triplet includes max miles constraint
|
600
|
-
# q.where :field.near => [lat, lng, miles]
|
601
|
-
#
|
602
|
-
# geopoint = Parse::GeoPoint.new(30.0, -20.0)
|
603
|
-
# PlaceObject.all :location.near => geopoint.max_miles(10)
|
604
|
-
#
|
605
|
-
# @todo Add support $maxDistanceInKilometers (for kms) and $maxDistanceInRadians (for radian angle).
|
606
|
-
class NearSphereQueryConstraint < Constraint
|
607
|
-
# @!method near
|
608
|
-
# A registered method on a symbol to create the constraint. Maps to Parse operator "$nearSphere".
|
609
|
-
# @example
|
584
|
+
# Equivalent to the `$nearSphere` Parse query operation. This is only applicable
|
585
|
+
# if the field is of type `GeoPoint`. This will query Parse and return a list of
|
586
|
+
# results ordered by distance with the nearest object being first.
|
587
|
+
#
|
610
588
|
# q.where :field.near => geopoint
|
589
|
+
#
|
590
|
+
# geopoint = Parse::GeoPoint.new(30.0, -20.0)
|
591
|
+
# PlaceObject.all :location.near => geopoint
|
592
|
+
# If you wish to constrain the geospatial query to a maximum number of _miles_,
|
593
|
+
# you can utilize the `max_miles` method on a `Parse::GeoPoint` object. This
|
594
|
+
# is equivalent to the `$maxDistanceInMiles` constraint used with `$nearSphere`.
|
595
|
+
#
|
611
596
|
# q.where :field.near => geopoint.max_miles(distance)
|
612
|
-
#
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
#
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
597
|
+
# # or provide a triplet includes max miles constraint
|
598
|
+
# q.where :field.near => [lat, lng, miles]
|
599
|
+
#
|
600
|
+
# geopoint = Parse::GeoPoint.new(30.0, -20.0)
|
601
|
+
# PlaceObject.all :location.near => geopoint.max_miles(10)
|
602
|
+
#
|
603
|
+
# @todo Add support $maxDistanceInKilometers (for kms) and $maxDistanceInRadians (for radian angle).
|
604
|
+
class NearSphereQueryConstraint < Constraint
|
605
|
+
# @!method near
|
606
|
+
# A registered method on a symbol to create the constraint. Maps to Parse operator "$nearSphere".
|
607
|
+
# @example
|
608
|
+
# q.where :field.near => geopoint
|
609
|
+
# q.where :field.near => geopoint.max_miles(distance)
|
610
|
+
# @return [NearSphereQueryConstraint]
|
611
|
+
contraint_keyword :$nearSphere
|
612
|
+
register :near
|
613
|
+
|
614
|
+
# @return [Hash] the compiled constraint.
|
615
|
+
def build
|
616
|
+
point = formatted_value
|
617
|
+
max_miles = nil
|
618
|
+
if point.is_a?(Array) && point.count > 1
|
619
|
+
max_miles = point[2] if point.count == 3
|
620
|
+
point = { __type: "GeoPoint", latitude: point[0], longitude: point[1] }
|
621
|
+
end
|
622
|
+
if max_miles.present? && max_miles > 0
|
623
|
+
return { @operation.operand => { key => point, :$maxDistanceInMiles => max_miles.to_f } }
|
624
|
+
end
|
625
|
+
{ @operation.operand => { key => point } }
|
626
626
|
end
|
627
|
-
{ @operation.operand => { key => point } }
|
628
|
-
end
|
629
627
|
|
630
|
-
|
628
|
+
end
|
631
629
|
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
# q.where :field.within_box => [soutwestGeoPoint, northeastGeoPoint]
|
639
|
-
#
|
640
|
-
# sw = Parse::GeoPoint.new 32.82, -117.23 # San Diego
|
641
|
-
# ne = Parse::GeoPoint.new 36.12, -115.31 # Las Vegas
|
642
|
-
#
|
643
|
-
# # get all PlaceObjects inside this bounding box
|
644
|
-
# PlaceObject.all :location.within_box => [sw,ne]
|
645
|
-
#
|
646
|
-
class WithinGeoBoxQueryConstraint < Constraint
|
647
|
-
# @!method within_box
|
648
|
-
# A registered method on a symbol to create the constraint. Maps to Parse operator "$within".
|
649
|
-
# @example
|
630
|
+
# Equivalent to the `$within` Parse query operation and `$box` geopoint
|
631
|
+
# constraint. The rectangular bounding box is defined by a southwest point as
|
632
|
+
# the first parameter, followed by the a northeast point. Please note that Geo
|
633
|
+
# box queries that cross the international date lines are not currently
|
634
|
+
# supported by Parse.
|
635
|
+
#
|
650
636
|
# q.where :field.within_box => [soutwestGeoPoint, northeastGeoPoint]
|
651
|
-
#
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
#
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
637
|
+
#
|
638
|
+
# sw = Parse::GeoPoint.new 32.82, -117.23 # San Diego
|
639
|
+
# ne = Parse::GeoPoint.new 36.12, -115.31 # Las Vegas
|
640
|
+
#
|
641
|
+
# # get all PlaceObjects inside this bounding box
|
642
|
+
# PlaceObject.all :location.within_box => [sw,ne]
|
643
|
+
#
|
644
|
+
class WithinGeoBoxQueryConstraint < Constraint
|
645
|
+
# @!method within_box
|
646
|
+
# A registered method on a symbol to create the constraint. Maps to Parse operator "$within".
|
647
|
+
# @example
|
648
|
+
# q.where :field.within_box => [soutwestGeoPoint, northeastGeoPoint]
|
649
|
+
# @return [WithinGeoBoxQueryConstraint]
|
650
|
+
contraint_keyword :$within
|
651
|
+
register :within_box
|
652
|
+
|
653
|
+
# @return [Hash] the compiled constraint.
|
654
|
+
def build
|
655
|
+
geopoint_values = formatted_value
|
656
|
+
unless geopoint_values.is_a?(Array) && geopoint_values.count == 2 &&
|
657
|
+
geopoint_values.first.is_a?(Parse::GeoPoint) && geopoint_values.last.is_a?(Parse::GeoPoint)
|
658
|
+
raise(ArgumentError, '[Parse::Query] Invalid query value parameter passed to `within_box` constraint. ' +
|
659
|
+
'Values in array must be `Parse::GeoPoint` objects and ' +
|
660
|
+
'it should be in an array format: [southwestPoint, northeastPoint]' )
|
661
|
+
end
|
662
|
+
{ @operation.operand => { :$within => { :$box => geopoint_values } } }
|
663
663
|
end
|
664
|
-
{ @operation.operand => { :$within => { :$box => geopoint_values } } }
|
665
664
|
end
|
666
665
|
|
667
666
|
end
|