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