parse-stack 1.5.3 → 1.6.0
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.
- 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
|