parse-stack 1.5.1 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Changes.md +15 -1
- data/Gemfile.lock +10 -10
- data/README.md +23 -9
- data/bin/console +3 -0
- data/lib/parse/api/analytics.rb +1 -1
- data/lib/parse/api/objects.rb +1 -1
- data/lib/parse/api/users.rb +1 -1
- data/lib/parse/client.rb +77 -40
- data/lib/parse/client/caching.rb +9 -5
- data/lib/parse/client/protocol.rb +47 -0
- data/lib/parse/client/request.rb +66 -37
- data/lib/parse/client/response.rb +39 -21
- data/lib/parse/model/acl.rb +4 -9
- data/lib/parse/model/associations/belongs_to.rb +97 -9
- data/lib/parse/model/associations/collection_proxy.rb +89 -29
- data/lib/parse/model/associations/has_many.rb +301 -28
- data/lib/parse/model/associations/has_one.rb +98 -4
- data/lib/parse/model/associations/pointer_collection_proxy.rb +48 -16
- data/lib/parse/model/associations/relation_collection_proxy.rb +61 -36
- data/lib/parse/model/bytes.rb +11 -5
- data/lib/parse/model/classes/installation.rb +50 -3
- data/lib/parse/model/classes/role.rb +7 -2
- data/lib/parse/model/classes/session.rb +21 -4
- data/lib/parse/model/classes/user.rb +122 -22
- data/lib/parse/model/core/actions.rb +7 -3
- data/lib/parse/model/core/properties.rb +14 -13
- data/lib/parse/model/core/querying.rb +16 -10
- data/lib/parse/model/core/schema.rb +2 -3
- data/lib/parse/model/date.rb +18 -12
- data/lib/parse/model/file.rb +77 -19
- data/lib/parse/model/geopoint.rb +70 -12
- data/lib/parse/model/model.rb +84 -8
- data/lib/parse/model/object.rb +225 -94
- data/lib/parse/model/pointer.rb +94 -13
- data/lib/parse/model/push.rb +76 -4
- data/lib/parse/query.rb +356 -41
- data/lib/parse/query/constraints.rb +399 -29
- data/lib/parse/query/ordering.rb +21 -8
- data/lib/parse/stack.rb +1 -0
- data/lib/parse/stack/version.rb +2 -1
- data/lib/parse/webhooks.rb +0 -24
- data/lib/parse/webhooks/payload.rb +54 -1
- data/lib/parse/webhooks/registration.rb +13 -2
- metadata +2 -2
data/lib/parse/model/pointer.rb
CHANGED
@@ -7,37 +7,97 @@ require 'active_support/inflector'
|
|
7
7
|
require 'active_support/core_ext'
|
8
8
|
require 'active_model_serializers'
|
9
9
|
require_relative 'model'
|
10
|
-
require 'active_model_serializers'
|
11
10
|
module Parse
|
12
11
|
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
12
|
+
# The Pointer class represents the pointer type in Parse and is the superclass
|
13
|
+
# of Parse::Object types. A pointer can be considered a type of Parse::Object
|
14
|
+
# in which only the class name and id is known. In most cases, you may not
|
15
|
+
# deal with Parse::Pointer objects directly if you have defined all your
|
16
|
+
# Parse::Object subclasses.
|
17
|
+
#
|
18
|
+
# A `Parse::Pointer` only contains data about the specific Parse class and
|
19
|
+
# the `id` for the object. Therefore, creating an instance of any
|
20
|
+
# Parse::Object subclass with only the `:id` field set will be
|
21
|
+
# considered in "pointer" state even though its specific class is not
|
22
|
+
# `Parse::Pointer` type. The only case that you may have a Parse::Pointer
|
23
|
+
# is in the case where an object was received for one of your classes and
|
24
|
+
# the framework has no registered class handler for it.
|
25
|
+
# Assume you have the tables `Post`, `Comment` and `Author` defined in your
|
26
|
+
# remote Parse database, but have only defined `Post` and `Commentary`
|
27
|
+
# locally.
|
28
|
+
# @example
|
29
|
+
# class Post < Parse::Object
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# class Commentary < Parse::Object
|
33
|
+
# belongs_to :post
|
34
|
+
# belongs_to :author
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# comment = Commentary.first
|
38
|
+
# comment.post? # true because it is non-nil
|
39
|
+
# comment.artist? # true because it is non-nil
|
40
|
+
#
|
41
|
+
# # both are true because they are in a Pointer state
|
42
|
+
# comment.post.pointer? # true
|
43
|
+
# comment.author.pointer? # true
|
44
|
+
#
|
45
|
+
# # we have defined a Post class handler
|
46
|
+
# comment.post # <Post @parse_class="Post", @id="xdqcCqfngz">
|
47
|
+
#
|
48
|
+
# # we have not defined an Author class handler
|
49
|
+
# comment.author # <Parse::Pointer @parse_class="Author", @id="hZLbW6ofKC">
|
50
|
+
#
|
51
|
+
#
|
52
|
+
# comment.post.fetch # fetch the relation
|
53
|
+
# comment.post.pointer? # false, it is now a full object.
|
54
|
+
#
|
55
|
+
# The effect is that for any unknown classes that the framework encounters,
|
56
|
+
# it will generate Parse::Pointer instances until you define those classes
|
57
|
+
# with valid properties and associations. While this might be ok for some
|
58
|
+
# classes you do not use, we still recommend defining all your Parse classes
|
59
|
+
# locally in the framework.
|
60
|
+
#
|
61
|
+
# Once you have a subclass, you may also create a Parse::Pointer object using
|
62
|
+
# the _pointer_ method.
|
63
|
+
# @example
|
64
|
+
# Parse::User.pointer("123456") # => Parse::Pointer for "_User" class
|
65
|
+
#
|
66
|
+
# @see Parse::Object
|
18
67
|
class Pointer < Model
|
19
68
|
ATTRIBUTES = { __type: :string, className: :string, objectId: :string}.freeze
|
20
|
-
|
69
|
+
# @return [String] the name of the Parse class for this pointer.
|
70
|
+
attr_accessor :parse_class
|
71
|
+
# @return [String] the objectId field
|
72
|
+
attr_accessor :id
|
21
73
|
|
22
|
-
|
74
|
+
# @return [Model::TYPE_POINTER]
|
75
|
+
def __type; Parse::Model::TYPE_POINTER; end;
|
23
76
|
alias_method :className, :parse_class
|
24
77
|
# A Parse object as a className field and objectId. In ruby, we will use the
|
25
78
|
# id attribute method, but for usability, we will also alias it to objectId
|
26
79
|
alias_method :objectId, :id
|
27
80
|
|
81
|
+
# A Parse pointer only requires the name of the remote Parse collection name,
|
82
|
+
# and the `objectId` of the record.
|
83
|
+
# @param table [String] The Parse class name in the Parse database.
|
84
|
+
# @param oid [String] The objectId
|
28
85
|
def initialize(table, oid)
|
29
86
|
@parse_class = table.to_s
|
30
87
|
@id = oid.to_s
|
31
88
|
end
|
32
89
|
|
90
|
+
# @return [String] the name of the collection for this Pointer.
|
33
91
|
def parse_class
|
34
92
|
@parse_class
|
35
93
|
end
|
36
94
|
|
95
|
+
# @return [Hash]
|
37
96
|
def attributes
|
38
97
|
ATTRIBUTES
|
39
98
|
end
|
40
99
|
|
100
|
+
# @return [Hash] serialized JSON structure
|
41
101
|
def json_hash
|
42
102
|
JSON.parse to_json
|
43
103
|
end
|
@@ -45,32 +105,44 @@ module Parse
|
|
45
105
|
# Create a new pointer with the current class name and id. While this may not make sense
|
46
106
|
# for a pointer instance, Parse::Object subclasses use this inherited method to turn themselves into
|
47
107
|
# pointer objects.
|
108
|
+
# @example
|
109
|
+
# user = Parse::User.first
|
110
|
+
# user.pointer # => Parse::Pointer("_User", user.id)
|
111
|
+
#
|
112
|
+
# @return [Pointer] a new Pointer for this object.
|
113
|
+
# @see Parse::Object
|
48
114
|
def pointer
|
49
115
|
Pointer.new parse_class, @id
|
50
116
|
end
|
51
117
|
|
52
|
-
#
|
53
|
-
# if we have a parse class and an id, but no
|
118
|
+
# Whether this instance is in pointer state. A pointer is determined
|
119
|
+
# if we have a parse class and an id, but no created_at or updated_at fields.
|
120
|
+
# @return [Boolean] true if instance is in pointer state.
|
54
121
|
def pointer?
|
55
122
|
present? && @created_at.blank? && @updated_at.blank?
|
56
123
|
end
|
57
124
|
|
58
|
-
#
|
125
|
+
# Returns true if the data for this instance has been fetched. Because of some autofetching
|
59
126
|
# mechanisms, this is useful to know whether the object already has data without actually causing
|
60
127
|
# a fetch of the data.
|
128
|
+
# @return [Boolean] true if not in pointer state.
|
61
129
|
def fetched?
|
62
130
|
present? && pointer? == false
|
63
131
|
end
|
64
132
|
|
65
133
|
# This method is a general implementation that gets overriden by Parse::Object subclass.
|
66
134
|
# Given the class name and the id, we will go to Parse and fetch the actual record, returning the
|
67
|
-
# JSON object.
|
135
|
+
# JSON object.
|
136
|
+
# @return [Parse::Object] the fetched Parse::Object, nil otherwise.
|
68
137
|
def fetch
|
69
138
|
response = client.fetch_object(parse_class, id)
|
70
139
|
return nil if response.error?
|
71
140
|
response.result
|
72
141
|
end
|
73
142
|
|
143
|
+
# Two Parse::Pointers (or Parse::Objects) are equal if both of them have
|
144
|
+
# the same Parse class and the same id.
|
145
|
+
# @return [Boolean]
|
74
146
|
def ==(o)
|
75
147
|
return false unless o.is_a?(Pointer)
|
76
148
|
#only equal if the Parse class and object ID are the same.
|
@@ -78,6 +150,7 @@ module Parse
|
|
78
150
|
end
|
79
151
|
alias_method :eql?, :==
|
80
152
|
|
153
|
+
# @return [Boolean] true if instance has a Parse class and an id.
|
81
154
|
def present?
|
82
155
|
parse_class.present? && @id.present?
|
83
156
|
end
|
@@ -87,14 +160,22 @@ end
|
|
87
160
|
|
88
161
|
# extensions
|
89
162
|
class Array
|
163
|
+
# This method maps all the ids (String) of all Parse::Objects in the array.
|
164
|
+
# @return [Array<String>] an array of strings of ids.
|
90
165
|
def objectIds
|
91
|
-
map { |m| m.is_?(Parse::Pointer) ? m.id : nil }.
|
166
|
+
map { |m| m.is_?(Parse::Pointer) ? m.id : nil }.compact
|
92
167
|
end
|
93
168
|
|
169
|
+
# Filter all objects in the array that do not inherit from Parse::Pointer or
|
170
|
+
# Parse::Object.
|
171
|
+
# @return [Array<Parse::Object,Parse::Pointer>] an array of Parse::Objects.
|
94
172
|
def valid_parse_objects
|
95
173
|
select { |s| s.is_a?(Parse::Pointer) }
|
96
174
|
end
|
97
175
|
|
176
|
+
# Convert all potential objects in the array to a list of Parse::Pointer instances.
|
177
|
+
# The array can contain a mixture of objects types including JSON Parse-like hashes.
|
178
|
+
# @return [Array<Parse::Pointer>] an array of Parse::Pointer objects.
|
98
179
|
def parse_pointers(table = nil)
|
99
180
|
self.map do |m|
|
100
181
|
#if its an exact Parse::Pointer
|
data/lib/parse/model/push.rb
CHANGED
@@ -5,19 +5,82 @@ require_relative '../query.rb'
|
|
5
5
|
require_relative '../client.rb'
|
6
6
|
require 'active_model_serializers'
|
7
7
|
module Parse
|
8
|
-
|
8
|
+
# This class represents the API to send push notification to devices that are
|
9
|
+
# available in the Installation table. Push notifications are implemented
|
10
|
+
# through the `Parse::Push` class. To send push notifications through the
|
11
|
+
# REST API, you must enable `REST push enabled?` option in the `Push
|
12
|
+
# Notification Settings` section of the `Settings` page in your Parse
|
13
|
+
# application. Push notifications targeting uses the Installation Parse
|
14
|
+
# class to determine which devices receive the notification. You can provide
|
15
|
+
# any query constraint, similar to using `Parse::Query`, in order to target
|
16
|
+
# the specific set of devices you want given the columns you have configured
|
17
|
+
# in your `Installation` class. The `Parse::Push` class supports many other
|
18
|
+
# options not listed here.
|
19
|
+
# @example
|
20
|
+
#
|
21
|
+
# push = Parse::Push.new
|
22
|
+
# push.send( "Hello World!") # to everyone
|
23
|
+
#
|
24
|
+
# # simple channel push
|
25
|
+
# push = Parse::Push.new
|
26
|
+
# push.channels = ["addicted2salsa"]
|
27
|
+
# push.send "You are subscribed to Addicted2Salsa!"
|
28
|
+
#
|
29
|
+
# # advanced targeting
|
30
|
+
# push = Parse::Push.new( {..where query constraints..} )
|
31
|
+
# # or use `where()`
|
32
|
+
# push.where :device_type.in => ['ios','android'], :location.near => some_geopoint
|
33
|
+
# push.alert = "Hello World!"
|
34
|
+
# push.sound = "soundfile.caf"
|
35
|
+
#
|
36
|
+
# # additional payload data
|
37
|
+
# push.data = { uri: "app://deep_link_path" }
|
38
|
+
#
|
39
|
+
# # Send the push
|
40
|
+
# push.send
|
41
|
+
#
|
42
|
+
#
|
9
43
|
class Push
|
10
44
|
include Client::Connectable
|
11
|
-
|
12
|
-
|
45
|
+
|
46
|
+
# @!attribute [rw] query
|
47
|
+
# Sending a push notification is done by performing a query against the Installation
|
48
|
+
# collection with a Parse::Query. This query contains the constraints that will be
|
49
|
+
# sent to Parse with the push payload.
|
50
|
+
# @return [Parse::Query] the query containing Installation constraints.
|
51
|
+
|
52
|
+
# @!attribute [rw] alert
|
53
|
+
# @return [String]
|
54
|
+
# @!attribute [rw] badge
|
55
|
+
# @return [Integer]
|
56
|
+
# @!attribute [rw] sound
|
57
|
+
# @return [String] the name of the sound file
|
58
|
+
# @!attribute [rw] title
|
59
|
+
# @return [String]
|
60
|
+
# @!attribute [rw] data
|
61
|
+
# @return [Hash] specific payload data.
|
62
|
+
# @!attribute [rw] expiration_time
|
63
|
+
# @return [Parse::Date]
|
64
|
+
# @!attribute [rw] expiration_interval
|
65
|
+
# @return [Integer]
|
66
|
+
# @!attribute [rw] push_time
|
67
|
+
# @return [Parse::Date]
|
68
|
+
# @!attribute [rw] channels
|
69
|
+
# @return [Array] an array of strings for subscribed channels.
|
70
|
+
attr_accessor :query, :alert, :badge, :sound, :title, :data,
|
71
|
+
:expiration_time, :expiration_interval, :push_time, :channels
|
13
72
|
|
14
73
|
alias_method :message, :alert
|
15
74
|
alias_method :message=, :alert=
|
16
75
|
|
76
|
+
# Send a push notification using a push notification hash
|
77
|
+
# @param payload [Hash] a push notification hash payload
|
17
78
|
def self.send(payload)
|
18
79
|
client.push payload.as_json
|
19
80
|
end
|
20
81
|
|
82
|
+
# Initialize a new push notification request.
|
83
|
+
# @param constraints [Hash] a set of query constraints
|
21
84
|
def initialize(constraints = {})
|
22
85
|
self.where constraints
|
23
86
|
end
|
@@ -26,6 +89,8 @@ module Parse
|
|
26
89
|
@query ||= Parse::Query.new(Parse::Model::CLASS_INSTALLATION)
|
27
90
|
end
|
28
91
|
|
92
|
+
# @!attribute [rw] where
|
93
|
+
# @return [Hash] a hash of 'where' query constraints
|
29
94
|
def where=(where_clausees)
|
30
95
|
query.where where_clauses
|
31
96
|
end
|
@@ -37,7 +102,7 @@ module Parse
|
|
37
102
|
end
|
38
103
|
|
39
104
|
def channels=(list)
|
40
|
-
@channels =
|
105
|
+
@channels = Array.wrap(list)
|
41
106
|
end
|
42
107
|
|
43
108
|
def data=(h)
|
@@ -48,14 +113,19 @@ module Parse
|
|
48
113
|
end
|
49
114
|
end
|
50
115
|
|
116
|
+
# @return [Hash] a JSON encoded hash.
|
51
117
|
def as_json(*args)
|
52
118
|
payload.as_json
|
53
119
|
end
|
54
120
|
|
121
|
+
# @return [String] a JSON encoded string.
|
55
122
|
def to_json(*args)
|
56
123
|
as_json.to_json
|
57
124
|
end
|
58
125
|
|
126
|
+
# This method takes all the parameters of the instance and creates a proper
|
127
|
+
# hash structure, required by Parse, in order to process the push notification.
|
128
|
+
# @return [Hash] the prepared push payload to be used in the request.
|
59
129
|
def payload
|
60
130
|
msg = {
|
61
131
|
data: {
|
@@ -91,6 +161,8 @@ module Parse
|
|
91
161
|
msg
|
92
162
|
end
|
93
163
|
|
164
|
+
# helper method to send a message
|
165
|
+
# @param message [String] the message to send
|
94
166
|
def send(message = nil)
|
95
167
|
@alert = message if message.is_a?(String)
|
96
168
|
@data = message if message.is_a?(Hash)
|
data/lib/parse/query.rb
CHANGED
@@ -12,27 +12,131 @@ require 'active_support/inflector'
|
|
12
12
|
require 'active_support/core_ext'
|
13
13
|
|
14
14
|
module Parse
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
15
|
+
# The {Parse::Query} class provides the lower-level querying interface for
|
16
|
+
# your Parse collections by utilizing the {http://parseplatform.github.io/docs/rest/guide/#queries
|
17
|
+
# REST Querying interface}. This is the main engine behind making Parse queries
|
18
|
+
# on remote collections. It takes a set of constraints and generates the
|
19
|
+
# proper hash parameters that are passed to an API request in order to retrive
|
20
|
+
# matching results. The querying design pattern is inspired from
|
21
|
+
# {http://datamapper.org/ DataMapper} where symbols are overloaded with
|
22
|
+
# specific methods with attached values.
|
23
|
+
#
|
24
|
+
# At the core of each item is a {Parse::Operation}. An operation is
|
21
25
|
# made up of a field name and an operator. Therefore calling
|
22
26
|
# something like :name.eq, defines an equality operator on the field
|
23
|
-
# name. Using Parse::
|
24
|
-
# constraints
|
25
|
-
|
27
|
+
# name. Using {Parse::Operation}s with values, we can build different types of
|
28
|
+
# constraints, known as {Parse::Constraint}s.
|
29
|
+
#
|
30
|
+
# This component can be used on its own without defining your models as all
|
31
|
+
# results are provided in hash form.
|
32
|
+
#
|
33
|
+
# *Field-Formatter*
|
34
|
+
#
|
35
|
+
# By convention in Ruby (see
|
36
|
+
# {https://github.com/bbatsov/ruby-style-guide#snake-case-symbols-methods-vars Style Guide}),
|
37
|
+
# symbols and variables are expressed in lower_snake_case form. Parse, however,
|
38
|
+
# prefers column names in {String#columnize} format (ex. `objectId`,
|
39
|
+
# `createdAt` and `updatedAt`). To keep in line with the style
|
40
|
+
# guides between the languages, we do the automatic conversion of the field
|
41
|
+
# names when compiling the query. This feature can be overridden by changing the
|
42
|
+
# value of {Parse::Query.field_formatter}.
|
43
|
+
#
|
44
|
+
# # default uses :columnize
|
45
|
+
# query = Parse::User.query :field_one => 1, :FieldTwo => 2, :Field_Three => 3
|
46
|
+
# query.compile_where # => {"fieldOne"=>1, "fieldTwo"=>2, "fieldThree"=>3}
|
47
|
+
#
|
48
|
+
# # turn off
|
49
|
+
# Parse::Query.field_formatter = nil
|
50
|
+
# query = Parse::User.query :field_one => 1, :FieldTwo => 2, :Field_Three => 3
|
51
|
+
# query.compile_where # => {"field_one"=>1, "FieldTwo"=>2, "Field_Three"=>3}
|
52
|
+
#
|
53
|
+
# # force everything camel case
|
54
|
+
# Parse::Query.field_formatter = :camelize
|
55
|
+
# query = Parse::User.query :field_one => 1, :FieldTwo => 2, :Field_Three => 3
|
56
|
+
# query.compile_where # => {"FieldOne"=>1, "FieldTwo"=>2, "FieldThree"=>3}
|
57
|
+
#
|
58
|
+
# Most of the constraints supported by Parse are available to `Parse::Query`.
|
59
|
+
# Assuming you have a column named `field`, here are some examples. For an
|
60
|
+
# explanation of the constraints, please see
|
61
|
+
# {http://parseplatform.github.io/docs/rest/guide/#queries Parse Query Constraints documentation}.
|
62
|
+
# You can build your own custom query constraints by creating a `Parse::Constraint`
|
63
|
+
# subclass. For all these `where` clauses assume `q` is a `Parse::Query` object.
|
26
64
|
class Query
|
27
65
|
extend ::ActiveModel::Callbacks
|
28
66
|
include Parse::Client::Connectable
|
29
67
|
include Enumerable
|
68
|
+
# @!group Callbacks
|
69
|
+
#
|
70
|
+
# @!method before_prepare
|
71
|
+
# A callback called before the query is compiled
|
72
|
+
# @yield A block to execute for the callback.
|
73
|
+
# @see ActiveModel::Callbacks
|
74
|
+
# @!method after_prepare
|
75
|
+
# A callback called after the query is compiled
|
76
|
+
# @yield A block to execute for the callback.
|
77
|
+
# @see ActiveModel::Callbacks
|
78
|
+
# @!endgroup
|
30
79
|
define_model_callbacks :prepare, only: [:after, :before]
|
31
80
|
# A query needs to be tied to a Parse table name (Parse class)
|
32
81
|
# The client object is of type Parse::Client in order to send query requests.
|
33
82
|
# You can modify the default client being used by all Parse::Query objects by setting
|
34
83
|
# Parse::Query.client. You can override individual Parse::Query object clients
|
35
84
|
# by changing their client variable to a different Parse::Client object.
|
85
|
+
|
86
|
+
# @!attribute [rw] table
|
87
|
+
# @return [String] the name of the Parse collection to query against.
|
88
|
+
# @!attribute [rw] client
|
89
|
+
# @return [Parse::Client] the client to use for the API Query request.
|
90
|
+
# @!attribute [rw] key
|
91
|
+
# This parameter is used to support `select` queries where you have to
|
92
|
+
# pass a `key` parameter for matching different tables.
|
93
|
+
# @return [String] the foreign key to match against.
|
94
|
+
# @!attribute [rw] cache
|
95
|
+
# Set whether this query should be cached and for how long. This parameter
|
96
|
+
# is used to cache queries when using {Parse::Middleware::Caching}. If
|
97
|
+
# the caching middleware is configured, all queries will be cached for the
|
98
|
+
# duration allowed by the cache, and therefore some queries could return
|
99
|
+
# cached results. To disable caching and cached results for this specific query,
|
100
|
+
# you may set this field to `false`. To specify the specific amount of time
|
101
|
+
# you want this query to be cached, set a duration (in number of seconds) that
|
102
|
+
# the caching middleware should cache this request.
|
103
|
+
# @example
|
104
|
+
# # find all users with name "Bob"
|
105
|
+
# query = Parse::Query.new("_User", :name => "Bob")
|
106
|
+
#
|
107
|
+
# query.cache = true # (default) cache using default cache duration.
|
108
|
+
#
|
109
|
+
# query.cache = 1.day # cache for 86400 seconds
|
110
|
+
#
|
111
|
+
# query.cache = false # do not cache or use cache results
|
112
|
+
#
|
113
|
+
# # You may optionally pass this into the constraint hash.
|
114
|
+
# query = Parse::Query.new("_User", :name => "Bob", :cache => 1.day)
|
115
|
+
#
|
116
|
+
# @return [Boolean] if set to true or false on whether it should use the default caching
|
117
|
+
# length set when configuring {Parse::Middleware::Caching}.
|
118
|
+
# @return [Integer] if set to a number of seconds to cache this specific request
|
119
|
+
# with the {Parse::Middleware::Caching}.
|
120
|
+
# @!attribute [rw] use_master_key
|
121
|
+
# True or false on whether we should send the master key in this request. If
|
122
|
+
# You have provided the master_key when initializing Parse, then all requests
|
123
|
+
# will send the master key by default. This feature is useful when you want to make
|
124
|
+
# a particular query be performed with public credentials, or on behalf of a user using
|
125
|
+
# a {session_token}. Default is set to true.
|
126
|
+
# @see #session_token
|
127
|
+
# @example
|
128
|
+
# # disable use of the master_key in the request.
|
129
|
+
# query = Parse::Query.new("_User", :name => "Bob", :master_key => false)
|
130
|
+
# @return [Boolean] whether we should send the master key in this request.
|
131
|
+
# @!attribute [rw] session_token
|
132
|
+
# Set the session token to send with this API request. A session token is tied to
|
133
|
+
# a logged in {Parse::User}. When sending a session_token in the request,
|
134
|
+
# this performs the query on behalf of the user (with their allowed priviledges).
|
135
|
+
# @example
|
136
|
+
# # perform this query as user represented by session_token
|
137
|
+
# query = Parse::Query.new("_User", :name => "Bob", :session_token => "r:XyX123...")
|
138
|
+
# @note Using a session_token automatically disables sending the master key in the request.
|
139
|
+
# @return [String] the session token to send with this API request.
|
36
140
|
attr_accessor :table, :client, :key, :cache, :use_master_key, :session_token
|
37
141
|
|
38
142
|
# We have a special class method to handle field formatting. This turns
|
@@ -44,11 +148,18 @@ module Parse
|
|
44
148
|
# in lower case). You can specify a different method to call by setting the Parse::Query.field_formatter
|
45
149
|
# variable with the symbol name of the method to call on the object. You can set this to nil
|
46
150
|
# if you do not want any field formatting to be performed.
|
151
|
+
|
47
152
|
@field_formatter = :columnize
|
48
153
|
class << self
|
49
|
-
#field
|
154
|
+
# The method to use when converting field names to Parse column names. Default is {String#columnize}.
|
155
|
+
# By convention Parse uses lowercase-first camelcase syntax for field/column names, but ruby
|
156
|
+
# uses snakecase. To support this methodology we process all field constraints through the method
|
157
|
+
# defined by the field formatter. You may set this to nil to turn off this functionality.
|
158
|
+
# @return [Symbol] The filter method to process column and field names. Default {String#columnize}.
|
50
159
|
attr_accessor :field_formatter
|
51
160
|
|
161
|
+
# @param str [String] the string to format
|
162
|
+
# @return [String] formatted string using {Parse::Query.field_formatter}.
|
52
163
|
def format_field(str)
|
53
164
|
res = str.to_s.strip
|
54
165
|
if field_formatter.present? && res.respond_to?(field_formatter)
|
@@ -57,18 +168,48 @@ module Parse
|
|
57
168
|
res
|
58
169
|
end
|
59
170
|
|
60
|
-
#
|
61
|
-
|
62
|
-
|
171
|
+
# Helper method to create a query with constraints for a specific Parse collection.
|
172
|
+
# Also sets the default limit count to `:max`.
|
173
|
+
# @param table [String] the name of the Parse collection to query. (ex. "_User")
|
174
|
+
# @param constraints [Hash] a set of query constraints.
|
175
|
+
# @return [Query] a new query for the Parse collection with the passed in constraints.
|
176
|
+
def all(table, constraints = {limit: :max})
|
177
|
+
self.new(table, constraints.reverse_merge({limit: :max}))
|
178
|
+
end
|
179
|
+
|
180
|
+
# This methods takes a set of constraints and merges them to build a final
|
181
|
+
# `where` constraint clause for sending to the Parse backend.
|
182
|
+
# @param where [Array] an array of {Parse::Constraint} objects.
|
183
|
+
# @return [Hash] a hash representing the compiled query
|
184
|
+
def compile_where(where)
|
185
|
+
constraint_reduce( where )
|
186
|
+
end
|
187
|
+
|
188
|
+
# @!visibility private
|
189
|
+
def constraint_reduce(clauses)
|
190
|
+
# @todo Need to add proper constraint merging
|
191
|
+
clauses.reduce({}) do |clause, subclause|
|
192
|
+
#puts "Merging Subclause: #{subclause.as_json}"
|
193
|
+
|
194
|
+
clause.deep_merge!( subclause.as_json || {} )
|
195
|
+
clause
|
196
|
+
end
|
63
197
|
end
|
64
198
|
|
65
199
|
end
|
66
200
|
|
201
|
+
# @!attribute [r] client
|
202
|
+
# @return [Parse::Client] the client to use for making the API request.
|
203
|
+
# @see Parse::Client::Connectable
|
67
204
|
def client
|
68
205
|
# use the set client or the default client.
|
69
206
|
@client ||= self.class.client
|
70
207
|
end
|
71
208
|
|
209
|
+
# Clear a specific clause of this query. This can be one of: :where, :order,
|
210
|
+
# :includes, :skip, :limit, :count, :keys or :results.
|
211
|
+
# @param item [:Symbol] the clause to clear.
|
212
|
+
# @return [self]
|
72
213
|
def clear(item = :results)
|
73
214
|
case item
|
74
215
|
when :where
|
@@ -89,10 +230,27 @@ module Parse
|
|
89
230
|
@keys = []
|
90
231
|
end
|
91
232
|
@results = nil
|
92
|
-
|
93
|
-
self
|
233
|
+
self # chaining
|
94
234
|
end
|
95
235
|
|
236
|
+
# Constructor method to create a query with constraints for a specific Parse collection.
|
237
|
+
# Also sets the default limit count to `:max`.
|
238
|
+
# @overload new(table)
|
239
|
+
# Create a query for this Parse collection name.
|
240
|
+
# @example
|
241
|
+
# Parse::Query.new "_User"
|
242
|
+
# Parse::Query.new "_Installation", :device_type => 'ios'
|
243
|
+
# @param table [String] the name of the Parse collection to query. (ex. "_User")
|
244
|
+
# @param constraints [Hash] a set of query constraints.
|
245
|
+
# @overload new(parseSubclass)
|
246
|
+
# Create a query for this Parse model (or anything that responds to {Parse::Object.parse_class}).
|
247
|
+
# @example
|
248
|
+
# Parse::Query.new Parse::User
|
249
|
+
# # assume Post < Parse::Object
|
250
|
+
# Parse::Query.new Post, like_count.gt => 0
|
251
|
+
# @param parseSubclass [Parse::Object] the Parse model constant
|
252
|
+
# @param constraints [Hash] a set of query constraints.
|
253
|
+
# @return [Query] a new query for the Parse collection with the passed in constraints.
|
96
254
|
def initialize(table, constraints = {})
|
97
255
|
table = table.to_s.to_parse_class if table.is_a?(Symbol)
|
98
256
|
table = table.parse_class if table.respond_to?(:parse_class)
|
@@ -108,9 +266,11 @@ module Parse
|
|
108
266
|
@cache = true
|
109
267
|
@use_master_key = true
|
110
268
|
conditions constraints
|
111
|
-
self # chaining
|
112
269
|
end # initialize
|
113
270
|
|
271
|
+
# Add a set of query expressions and constraints.
|
272
|
+
# @param expressions
|
273
|
+
# @return [self]
|
114
274
|
def conditions(expressions = {})
|
115
275
|
expressions.each do |expression, value|
|
116
276
|
if expression == :order
|
@@ -144,12 +304,29 @@ module Parse
|
|
144
304
|
@table = t.to_s.camelize
|
145
305
|
end
|
146
306
|
|
147
|
-
# returns the query
|
307
|
+
# returns the query clause for the particular clause
|
308
|
+
# @param clause_name [Symbol] One of supported clauses to return: :keys,
|
309
|
+
# :where, :order, :includes, :limit, :skip
|
310
|
+
# @return [Object] the content of the clause for this query.
|
148
311
|
def clause(clause_name = :where)
|
149
312
|
return unless [:keys, :where, :order, :includes, :limit, :skip].include?(clause_name)
|
150
313
|
instance_variable_get "@#{clause_name}".to_sym
|
151
314
|
end
|
152
315
|
|
316
|
+
# Restrict the fields returned by the query. This is useful for larger query
|
317
|
+
# results set where some of the data will not be used, which reduces network
|
318
|
+
# traffic and deserialization performance.
|
319
|
+
# @example
|
320
|
+
# # results only contain :name field
|
321
|
+
# Song.all :keys => :name
|
322
|
+
#
|
323
|
+
# # multiple keys
|
324
|
+
# Song.all :keys => [:name,:artist]
|
325
|
+
# @note Use this feature with caution when working with the results, as
|
326
|
+
# values for the fields not specified in the query will be omitted in
|
327
|
+
# the resulting object.
|
328
|
+
# @param fields [Array] the name of the fields to return.
|
329
|
+
# @return [self]
|
153
330
|
def keys(*fields)
|
154
331
|
@keys ||= []
|
155
332
|
fields.flatten.each do |field|
|
@@ -162,6 +339,16 @@ module Parse
|
|
162
339
|
self # chaining
|
163
340
|
end
|
164
341
|
|
342
|
+
# Add a sorting order for the query.
|
343
|
+
# @example
|
344
|
+
# # order updated_at ascending order
|
345
|
+
# Song.all :order => :updated_at
|
346
|
+
#
|
347
|
+
# # first order by highest like_count, then by ascending name.
|
348
|
+
# # Note that ascending is the default if not specified (ex. `:name.asc`)
|
349
|
+
# Song.all :order => [:like_count.desc, :name]
|
350
|
+
# @param ordering [Parse::Order] an ordering
|
351
|
+
# @return [self]
|
165
352
|
def order(*ordering)
|
166
353
|
@order ||= []
|
167
354
|
ordering.flatten.each do |order|
|
@@ -175,6 +362,13 @@ module Parse
|
|
175
362
|
self #chaining
|
176
363
|
end #order
|
177
364
|
|
365
|
+
# Use with limit to paginate through results. Default is 0 with
|
366
|
+
# maximum value being 10,000.
|
367
|
+
# @example
|
368
|
+
# # get the next 3 songs after the first 10
|
369
|
+
# Song.all :limit => 3, :skip => 10
|
370
|
+
# @param count [Integer] The number of records to skip.
|
371
|
+
# @return [self]
|
178
372
|
def skip(count)
|
179
373
|
# min <= count <= max
|
180
374
|
@skip = [ 0, count.to_i, 10_000].sort[1]
|
@@ -182,6 +376,19 @@ module Parse
|
|
182
376
|
self #chaining
|
183
377
|
end
|
184
378
|
|
379
|
+
# Limit the number of objects returned by the query. The default is 100, with
|
380
|
+
# Parse allowing a maximum of 1000. The framework also allows a value of
|
381
|
+
# `:max`. Utilizing this will have the framework continually intelligently
|
382
|
+
# utilize `:skip` to continue to paginate through results until an empty
|
383
|
+
# result set is received or the `:skip` limit is reached (10,000). When
|
384
|
+
# utilizing `all()`, `:max` is the default option for `:limit`.
|
385
|
+
# @example
|
386
|
+
# Song.all :limit => 1 # same as Song.first
|
387
|
+
# Song.all :limit => 1000 # maximum allowed by Parse
|
388
|
+
# Song.all :limit => :max # up to 11,000 records (theoretical).
|
389
|
+
# @param count [Integer,Symbol] The number of records to return. You may pass :max
|
390
|
+
# to get as many as 11_000 records with the aid if skipping.
|
391
|
+
# @return [self]
|
185
392
|
def limit(count)
|
186
393
|
if count == :max || count == :all
|
187
394
|
@limit = 11_000
|
@@ -201,6 +408,19 @@ module Parse
|
|
201
408
|
self #chaining
|
202
409
|
end
|
203
410
|
|
411
|
+
# Set a list of Parse Pointer columns to be fetched for matching records.
|
412
|
+
# You may chain multiple columns with the `.` operator.
|
413
|
+
# @example
|
414
|
+
# # assuming an 'Artist' has a pointer column for a 'Manager'
|
415
|
+
# # and a Song has a pointer column for an 'Artist'.
|
416
|
+
#
|
417
|
+
# # include the full artist object
|
418
|
+
# Song.all(:includes => [:artist])
|
419
|
+
#
|
420
|
+
# # Chaining - fetches the artist and the artist's manager for matching songs
|
421
|
+
# Song.all :includes => ['artist.manager']
|
422
|
+
# @param fields [Array] the list of Pointer columns to fetch.
|
423
|
+
# @return [self]
|
204
424
|
def includes(*fields)
|
205
425
|
@includes ||= []
|
206
426
|
fields.flatten.each do |field|
|
@@ -212,14 +432,27 @@ module Parse
|
|
212
432
|
@results = nil if fields.count > 0
|
213
433
|
self # chaining
|
214
434
|
end
|
215
|
-
alias_method :include, :includes
|
216
435
|
|
436
|
+
# Combine a list of {Parse::Constraint} objects
|
437
|
+
# @param list [Array<Parse::Constraint>] an array of Parse::Constraint subclasses.
|
438
|
+
# @return [self]
|
217
439
|
def add_constraints(list)
|
218
440
|
list = Array.wrap(list).select { |m| m.is_a?(Parse::Constraint) }
|
219
441
|
@where = @where + list
|
220
442
|
self
|
221
443
|
end
|
222
444
|
|
445
|
+
# Add a constraint to the query. This is mainly used internally for compiling constraints.
|
446
|
+
# @example
|
447
|
+
# # add where :field equals "value"
|
448
|
+
# query.add_constraint(:field.eq, "value")
|
449
|
+
#
|
450
|
+
# # add where :like_count is greater than 20
|
451
|
+
# query.add_constraint(:like_count.gt, 20)
|
452
|
+
#
|
453
|
+
# @param operator [Parse::Operator] an operator object containing the operation and operand.
|
454
|
+
# @param value [Object] the value for the constraint.
|
455
|
+
# @return [self]
|
223
456
|
def add_constraint(operator, value = nil, **opts)
|
224
457
|
@where ||= []
|
225
458
|
constraint = operator # assume Parse::Constraint
|
@@ -242,10 +475,26 @@ module Parse
|
|
242
475
|
self #chaining
|
243
476
|
end
|
244
477
|
|
478
|
+
# @return [Array<Parse::Constraint>] an array of constraints
|
479
|
+
# composing the :where clause for this query.
|
245
480
|
def constraints
|
246
481
|
@where
|
247
482
|
end
|
248
483
|
|
484
|
+
# Add additional query constraints to the `where` clause. The `where` clause
|
485
|
+
# is based on utilizing a set of constraints on the defined column names in
|
486
|
+
# your Parse classes. The constraints are implemented as method operators on
|
487
|
+
# field names that are tied to a value. Any symbol/string that is not one of
|
488
|
+
# the main expression keywords described here will be considered as a type of
|
489
|
+
# query constraint for the `where` clause in the query.
|
490
|
+
# @example
|
491
|
+
# # parts of a single where constraint
|
492
|
+
# { :column.constraint => value }
|
493
|
+
# @see Parse::Constraint
|
494
|
+
# @param conditions [Hash] a set of constraints for this query.
|
495
|
+
# @param opts [Hash] a set of options when adding the constraints. This is
|
496
|
+
# specific for each Parse::Constraint.
|
497
|
+
# @return [self]
|
249
498
|
def where(conditions = nil, opts = {})
|
250
499
|
return @where if conditions.nil?
|
251
500
|
if conditions.is_a?(Hash)
|
@@ -256,6 +505,22 @@ module Parse
|
|
256
505
|
self #chaining
|
257
506
|
end
|
258
507
|
|
508
|
+
# Combine two where clauses into an OR constraint. Equivalent to the `$or`
|
509
|
+
# Parse query operation. This is useful if you want to find objects that
|
510
|
+
# match several queries. We overload the `|` operator in order to have a
|
511
|
+
# clean syntax for joining these `or` operations.
|
512
|
+
# @example
|
513
|
+
# query = Player.where(:wins.gt => 150)
|
514
|
+
# query.or_where(:wins.lt => 5)
|
515
|
+
# # where wins > 150 || wins < 5
|
516
|
+
# results = query.results
|
517
|
+
#
|
518
|
+
# # or_query = query1 | query2 | query3 ...
|
519
|
+
# # ex. where wins > 150 || wins < 5
|
520
|
+
# query = Player.where(:wins.gt => 150) | Player.where(:wins.lt => 5)
|
521
|
+
# results = query.results
|
522
|
+
# @param where_clauses [Array<Parse::Constraint>] a list of Parse::Constraint objects to combine.
|
523
|
+
# @return [Query] the combined query with an OR clause.
|
259
524
|
def or_where(where_clauses = [])
|
260
525
|
where_clauses = where_clauses.where if where_clauses.is_a?(Parse::Query)
|
261
526
|
where_clauses = Parse::Query.new(@table, where_clauses ).where if where_clauses.is_a?(Hash)
|
@@ -277,6 +542,8 @@ module Parse
|
|
277
542
|
self #chaining
|
278
543
|
end
|
279
544
|
|
545
|
+
# @see #or_where
|
546
|
+
# @return [Query] the combined query with an OR clause.
|
280
547
|
def |(other_query)
|
281
548
|
raise ArgumentError, "Parse queries must be of the same class #{@table}." unless @table == other_query.table
|
282
549
|
copy_query = self.clone
|
@@ -284,6 +551,16 @@ module Parse
|
|
284
551
|
copy_query
|
285
552
|
end
|
286
553
|
|
554
|
+
# Perform a count query.
|
555
|
+
# @example
|
556
|
+
# # get number of songs with a play_count > 10
|
557
|
+
# Song.count :play_count.gt => 10
|
558
|
+
#
|
559
|
+
# # same
|
560
|
+
# query = Parse::Query.new("Song")
|
561
|
+
# query.where :play_count.gt => 10
|
562
|
+
# query.count
|
563
|
+
# @return [Integer] the count result
|
287
564
|
def count
|
288
565
|
old_value = @count
|
289
566
|
@count = 1
|
@@ -292,36 +569,47 @@ module Parse
|
|
292
569
|
res
|
293
570
|
end
|
294
571
|
|
572
|
+
# @yield a block yield for each object in the result
|
573
|
+
# @return [Array]
|
574
|
+
# @see Array#each
|
295
575
|
def each
|
296
576
|
return results.enum_for(:each) unless block_given? # Sparkling magic!
|
297
577
|
results.each(&Proc.new)
|
298
578
|
end
|
299
579
|
|
580
|
+
# @yield a block yield for each object in the result
|
581
|
+
# @return [Array]
|
582
|
+
# @see Array#map
|
300
583
|
def map
|
301
584
|
return results.enum_for(:map) unless block_given? # Sparkling magic!
|
302
585
|
results.map(&Proc.new)
|
303
586
|
end
|
304
587
|
|
588
|
+
# @yield a block yield for each object in the result
|
589
|
+
# @return [Array]
|
590
|
+
# @see Array#select
|
305
591
|
def select
|
306
592
|
return results.enum_for(:select) unless block_given? # Sparkling magic!
|
307
593
|
results.select(&Proc.new)
|
308
594
|
end
|
309
595
|
|
596
|
+
# @return [Array]
|
597
|
+
# @see Array#to_a
|
310
598
|
def to_a
|
311
599
|
results.to_a
|
312
600
|
end
|
313
601
|
|
314
|
-
|
315
|
-
|
316
|
-
results.select(&Proc.new)
|
317
|
-
end
|
318
|
-
|
602
|
+
# @param limit [Integer] the number of first items to return.
|
603
|
+
# @return [Parse::Object] the first object from the result.
|
319
604
|
def first(limit = 1)
|
320
605
|
@results = nil if @limit != limit
|
321
606
|
@limit = limit
|
322
607
|
limit == 1 ? results.first : results.first(limit)
|
323
608
|
end
|
324
609
|
|
610
|
+
# max_results is used to iterate through as many API requests as possible using
|
611
|
+
# :skip and :limit paramter.
|
612
|
+
# @!visibility private
|
325
613
|
def max_results(raw: false)
|
326
614
|
compiled_query = compile
|
327
615
|
query_limit = compiled_query[:limit] ||= 1_000
|
@@ -331,10 +619,9 @@ module Parse
|
|
331
619
|
results = []
|
332
620
|
|
333
621
|
iterations.times do |idx|
|
334
|
-
#puts "Fetching 1000 after #{compiled_query[:skip]}"
|
335
622
|
response = fetch!( compiled_query )
|
336
623
|
break if response.error? || response.results.empty?
|
337
|
-
|
624
|
+
|
338
625
|
items = response.results
|
339
626
|
items = decode(items) unless raw
|
340
627
|
|
@@ -353,6 +640,7 @@ module Parse
|
|
353
640
|
results
|
354
641
|
end
|
355
642
|
|
643
|
+
# @!visibility private
|
356
644
|
def _opts
|
357
645
|
opts = {}
|
358
646
|
opts[:cache] = self.cache || false
|
@@ -365,6 +653,9 @@ module Parse
|
|
365
653
|
opts
|
366
654
|
end
|
367
655
|
|
656
|
+
# Performs the fetch request for the query.
|
657
|
+
# @param compiled_query [Hash] the compiled query
|
658
|
+
# @return [Parse::Response] a response for a query request.
|
368
659
|
def fetch!(compiled_query)
|
369
660
|
|
370
661
|
response = client.find_objects(@table, compiled_query.as_json, _opts )
|
@@ -375,6 +666,27 @@ module Parse
|
|
375
666
|
end
|
376
667
|
alias_method :execute!, :fetch!
|
377
668
|
|
669
|
+
# Executes the query and builds the result set of Parse::Objects that matched.
|
670
|
+
# When this method is passed a block, the block is yielded for each matching item
|
671
|
+
# in the result, and the items are not returned. This methodology is more performant
|
672
|
+
# as large quantifies of objects are fetched in batches and all of them do
|
673
|
+
# not have to be kept in memory after the query finishes executing. This is the recommended
|
674
|
+
# method of processing large result sets.
|
675
|
+
# @example
|
676
|
+
# query = Parse::Query.new("_User", :created_at.before => DateTime.now)
|
677
|
+
# users = query.results # => Array of Parse::User objects.
|
678
|
+
#
|
679
|
+
# query = Parse::Query.new("_User", limit: :max)
|
680
|
+
#
|
681
|
+
# query.results do |user|
|
682
|
+
# # recommended; more memory efficient
|
683
|
+
# end
|
684
|
+
#
|
685
|
+
# @param raw [Boolean] whether to get the raw hash results of the query instead of
|
686
|
+
# a set of Parse::Object subclasses.
|
687
|
+
# @yield a block to iterate for each object that matched the query.
|
688
|
+
# @return [Array<Hash>] if raw is set to true, a set of Parse JSON hashes.
|
689
|
+
# @return [Array<Parse::Object>] if raw is set to false, a list of matching Parse::Object subclasses.
|
378
690
|
def results(raw: false)
|
379
691
|
if @results.nil?
|
380
692
|
if @limit.nil? || @limit.to_i <= 1_000
|
@@ -393,18 +705,32 @@ module Parse
|
|
393
705
|
end
|
394
706
|
alias_method :result, :results
|
395
707
|
|
708
|
+
# Builds objects based on the set of Parse JSON hashes in an array.
|
709
|
+
# @param list [Array<Hash>] a list of Parse JSON hashes
|
710
|
+
# @return [Array<Parse::Object>] an array of Parse::Object subclasses.
|
396
711
|
def decode(list)
|
397
712
|
list.map { |m| Parse::Object.build(m, @table) }.compact
|
398
713
|
end
|
399
714
|
|
715
|
+
# @return [Hash]
|
400
716
|
def as_json(*args)
|
401
717
|
compile.as_json
|
402
718
|
end
|
403
719
|
|
720
|
+
# Returns a compiled query without encoding the where clause.
|
721
|
+
# @param includeClassName [Boolean] whether to include the class name of the collection
|
722
|
+
# in the resulting compiled query.
|
723
|
+
# @return [Hash] a hash representing the prepared query request.
|
404
724
|
def prepared(includeClassName: false)
|
405
725
|
compile(encode: false, includeClassName: includeClassName)
|
406
726
|
end
|
407
727
|
|
728
|
+
# Complies the query and runs all prepare callbacks.
|
729
|
+
# @param encode [Boolean] whether to encode the `where` clause to a JSON string.
|
730
|
+
# @param includeClassName [Boolean] whether to include the class name of the collection.
|
731
|
+
# @return [Hash] a hash representing the prepared query request.
|
732
|
+
# @see #before_prepare
|
733
|
+
# @see #after_prepare
|
408
734
|
def compile(encode: true, includeClassName: false)
|
409
735
|
run_callbacks :prepare do
|
410
736
|
q = {} #query
|
@@ -432,26 +758,15 @@ module Parse
|
|
432
758
|
end
|
433
759
|
end
|
434
760
|
|
761
|
+
# @return [Hash] a hash representing just the `where` clause of this query.
|
435
762
|
def compile_where
|
436
763
|
self.class.compile_where( @where || [] )
|
437
764
|
end
|
438
765
|
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
def self.constraint_reduce(clauses)
|
444
|
-
# TODO: Need to add proper constraint merging
|
445
|
-
clauses.reduce({}) do |clause, subclause|
|
446
|
-
#puts "Merging Subclause: #{subclause.as_json}"
|
447
|
-
|
448
|
-
clause.deep_merge!( subclause.as_json || {} )
|
449
|
-
clause
|
450
|
-
end
|
451
|
-
end
|
452
|
-
|
453
|
-
def print
|
454
|
-
puts JSON.pretty_generate( as_json )
|
766
|
+
# Retruns a formatted JSON string representing the query, useful for debugging.
|
767
|
+
# @return [String]
|
768
|
+
def pretty
|
769
|
+
JSON.pretty_generate( as_json )
|
455
770
|
end
|
456
771
|
|
457
772
|
end # Query
|