parse-stack 1.5.2 → 1.5.3
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 +5 -0
- data/Gemfile.lock +1 -1
- data/README.md +40 -80
- data/lib/parse/api/all.rb +7 -0
- data/lib/parse/api/analytics.rb +8 -3
- data/lib/parse/api/apps.rb +29 -1
- data/lib/parse/api/batch.rb +14 -129
- data/lib/parse/api/cloud_functions.rb +9 -0
- data/lib/parse/api/config.rb +10 -1
- data/lib/parse/api/files.rb +7 -2
- data/lib/parse/api/hooks.rb +45 -2
- data/lib/parse/api/objects.rb +43 -6
- data/lib/parse/api/push.rb +6 -1
- data/lib/parse/api/schemas.rb +15 -1
- data/lib/parse/api/sessions.rb +5 -0
- data/lib/parse/api/users.rb +64 -5
- data/lib/parse/client/authentication.rb +25 -8
- data/lib/parse/client/batch.rb +206 -0
- data/lib/parse/client/body_builder.rb +12 -6
- data/lib/parse/client/caching.rb +42 -10
- data/lib/parse/client/protocol.rb +51 -46
- data/lib/parse/client/response.rb +1 -47
- data/lib/parse/client.rb +171 -42
- data/lib/parse/model/acl.rb +184 -39
- data/lib/parse/model/associations/belongs_to.rb +1 -0
- data/lib/parse/model/classes/role.rb +7 -1
- data/lib/parse/model/classes/session.rb +7 -3
- data/lib/parse/model/classes/user.rb +107 -0
- data/lib/parse/model/core/actions.rb +166 -115
- data/lib/parse/model/core/fetching.rb +105 -0
- data/lib/parse/model/core/properties.rb +40 -13
- data/lib/parse/model/core/querying.rb +123 -39
- data/lib/parse/model/core/schema.rb +22 -32
- data/lib/parse/model/object.rb +26 -20
- data/lib/parse/model/pointer.rb +1 -0
- data/lib/parse/query/constraint.rb +65 -27
- data/lib/parse/query/constraints.rb +0 -3
- data/lib/parse/query/operation.rb +33 -22
- data/lib/parse/query/ordering.rb +10 -5
- data/lib/parse/stack/generators/rails.rb +5 -1
- data/lib/parse/stack/generators/templates/model_installation.rb +1 -1
- data/lib/parse/stack/generators/templates/model_role.rb +1 -1
- data/lib/parse/stack/generators/templates/model_session.rb +2 -2
- data/lib/parse/stack/generators/templates/model_user.rb +1 -1
- data/lib/parse/stack/generators/templates/parse.rb +0 -1
- data/lib/parse/stack/railtie.rb +1 -0
- data/lib/parse/stack/tasks.rb +3 -1
- data/lib/parse/stack/version.rb +3 -1
- data/lib/parse/webhooks/registration.rb +3 -3
- data/lib/parse/webhooks.rb +88 -7
- metadata +5 -3
@@ -4,15 +4,62 @@
|
|
4
4
|
require_relative '../../query'
|
5
5
|
|
6
6
|
module Parse
|
7
|
-
|
7
|
+
# Defines the querying methods applied to a Parse::Object.
|
8
8
|
module Querying
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
10
|
+
# This feature is a small subset of the
|
11
|
+
# {http://guides.rubyonrails.org/active_record_querying.html#scopes
|
12
|
+
# ActiveRecord named scopes} feature. Scoping allows you to specify
|
13
|
+
# commonly-used queries which can be referenced as class method calls and
|
14
|
+
# are chainable with other scopes. You can use every {Parse::Query}
|
15
|
+
# method previously covered such as `where`, `includes` and `limit`.
|
16
|
+
#
|
17
|
+
# class Article < Parse::Object
|
18
|
+
# property :published, :boolean
|
19
|
+
# scope :published, -> { query(published: true) }
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# This is the same as defining your own class method for the query.
|
23
|
+
#
|
24
|
+
# class Article < Parse::Object
|
25
|
+
# def self.published
|
26
|
+
# query(published: true)
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# You can also chain scopes and pass parameters. In addition, boolean and
|
31
|
+
# enumerated properties have automatically generated scopes for you to use.
|
32
|
+
#
|
33
|
+
# class Article < Parse::Object
|
34
|
+
# scope :published, -> { query(published: true) }
|
35
|
+
#
|
36
|
+
# property :comment_count, :integer
|
37
|
+
# property :category
|
38
|
+
# property :approved, :boolean
|
39
|
+
#
|
40
|
+
# scope :published_and_commented, -> { published.where :comment_count.gt => 0 }
|
41
|
+
# scope :popular_topics, ->(name) { published_and_commented.where category: name }
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# # simple scope
|
45
|
+
# Article.published # => where published is true
|
46
|
+
#
|
47
|
+
# # chained scope
|
48
|
+
# Article.published_and_commented # published is true and comment_count > 0
|
49
|
+
#
|
50
|
+
# # scope with parameters
|
51
|
+
# Article.popular_topic("music") # => popular music articles
|
52
|
+
# # equivalent: where(published: true, :comment_count.gt => 0, category: name)
|
53
|
+
#
|
54
|
+
# # automatically generated scope
|
55
|
+
# Article.approved(category: "tour") # => where approved: true, category: 'tour'
|
56
|
+
#
|
57
|
+
# If you would like to turn off automatic scope generation for property types,
|
58
|
+
# set the option `:scope` to false when declaring the property.
|
59
|
+
# @param name [Symbol] the name of the scope.
|
60
|
+
# @param body [Proc] the proc related to the scope.
|
61
|
+
# @raise ArgumentError if body parameter does not respond to `call`
|
62
|
+
# @return [Symbol] the name of the singleton method created.
|
16
63
|
def scope(name, body)
|
17
64
|
unless body.respond_to?(:call)
|
18
65
|
raise ArgumentError, 'The scope body needs to be callable.'
|
@@ -60,33 +107,59 @@ module Parse
|
|
60
107
|
end
|
61
108
|
|
62
109
|
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
66
|
-
|
110
|
+
# Creates a new {Parse::Query} with the given constraints for this class.
|
111
|
+
# @example
|
112
|
+
# # assume Post < Parse::Object
|
113
|
+
# query = Post.query(:updated_at.before => DateTime.now)
|
114
|
+
# @return [Parse::Query] a new query with the given constraints for this
|
115
|
+
# Parse::Object subclass.
|
67
116
|
def query(constraints = {})
|
68
117
|
Parse::Query.new self.parse_class, constraints
|
69
118
|
end; alias_method :where, :query
|
70
119
|
|
71
|
-
|
72
|
-
|
120
|
+
# @param conditions (see Parse::Query#where)
|
121
|
+
# @return (see Parse::Query#where)
|
122
|
+
# @see Parse::Query#where
|
123
|
+
def literal_where(conditions = {})
|
124
|
+
query.where(conditions)
|
73
125
|
end
|
74
126
|
|
75
|
-
#
|
76
|
-
#
|
77
|
-
|
78
|
-
|
79
|
-
|
127
|
+
# Fetch all matching objects in this collection matching the constraints.
|
128
|
+
# This will be the most common way when querying Parse objects for a subclass.
|
129
|
+
# When no block is passed, all objects are returned. Using a block is more memory
|
130
|
+
# efficient as matching objects are fetched in batches and discarded after the iteration
|
131
|
+
# is completed.
|
132
|
+
# @param constraints [Hash] a set of {Parse::Query} constraints.
|
133
|
+
# @yield a block to iterate with each matching object.
|
134
|
+
# @example
|
135
|
+
#
|
136
|
+
# songs = Song.all( ... expressions ...) # => array of Parse::Objects
|
137
|
+
# # memory efficient for large amounts of records.
|
138
|
+
# Song.all( ... expressions ...) do |song|
|
139
|
+
# # ... do something with song..
|
140
|
+
# end
|
141
|
+
#
|
142
|
+
# @return [Array<Parse::Object>] an array of matching objects. If a block is passed,
|
143
|
+
# an empty array is returned.
|
144
|
+
def all(constraints = {limit: :max})
|
145
|
+
constraints = constraints.reverse_merge({limit: :max})
|
80
146
|
prepared_query = query(constraints)
|
81
147
|
return prepared_query.results(&Proc.new) if block_given?
|
82
148
|
prepared_query.results
|
83
149
|
end
|
84
150
|
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
|
151
|
+
# Returns the first item matching the constraint.
|
152
|
+
# @overload first(count = 1)
|
153
|
+
# @param count [Interger] The number of items to return.
|
154
|
+
# @example
|
155
|
+
# Object.first(2) # => an array of the first 2 objects in the collection.
|
156
|
+
# @return [Parse::Object] if count == 1
|
157
|
+
# @return [Array<Parse::Object>] if count > 1
|
158
|
+
# @overload first(constraints = {})
|
159
|
+
# @param constraints [Hash] a set of {Parse::Query} constraints.
|
160
|
+
# @example
|
161
|
+
# Object.first( :name => "Anthony" )
|
162
|
+
# @return [Parse::Object] the first matching object.
|
90
163
|
def first(constraints = {})
|
91
164
|
fetch_count = 1
|
92
165
|
if constraints.is_a?(Numeric)
|
@@ -99,12 +172,20 @@ module Parse
|
|
99
172
|
return res.first fetch_count
|
100
173
|
end
|
101
174
|
|
102
|
-
#
|
103
|
-
|
175
|
+
# Creates a count request which is more performant when counting objects.
|
176
|
+
# @example
|
177
|
+
# # number of songs with a like count greater than 20.
|
178
|
+
# count = Song.count( :like_count.gt => 20 )
|
179
|
+
# @param constraints (see #all)
|
180
|
+
# @return [Interger] the number of records matching the query.
|
181
|
+
# @see Parse::Query#count
|
104
182
|
def count(constraints = {})
|
105
183
|
query(constraints).count
|
106
184
|
end
|
107
185
|
|
186
|
+
# Find objects matching the constraint ordered by the descending created_at date.
|
187
|
+
# @param constraints (see #all)
|
188
|
+
# @return [Array<Parse::Object>]
|
108
189
|
def newest(constraints = {})
|
109
190
|
constraints.merge!(order: :created_at.desc)
|
110
191
|
_q = query(constraints)
|
@@ -112,6 +193,9 @@ module Parse
|
|
112
193
|
_q
|
113
194
|
end
|
114
195
|
|
196
|
+
# Find objects matching the constraint ordered by the ascending created_at date.
|
197
|
+
# @param constraints (see #all)
|
198
|
+
# @return [Array<Parse::Object>]
|
115
199
|
def oldest(constraints = {})
|
116
200
|
constraints.merge!(order: :created_at.asc)
|
117
201
|
_q = query(constraints)
|
@@ -119,18 +203,20 @@ module Parse
|
|
119
203
|
_q
|
120
204
|
end
|
121
205
|
|
122
|
-
# Find objects
|
123
|
-
# objects that were successfully found.
|
124
|
-
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
129
|
-
# type
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
133
|
-
|
206
|
+
# Find objects for a given objectId in this collection.The result is a list
|
207
|
+
# (or single item) of the objects that were successfully found.
|
208
|
+
# @example
|
209
|
+
# Object.find "<objectId>"
|
210
|
+
# Object.find "<objectId>", "<objectId>"....
|
211
|
+
# Object.find ["<objectId>", "<objectId>"]
|
212
|
+
# @param parse_ids [String] the objectId to find.
|
213
|
+
# @param type [Symbol] the fetching methodology to use if more than one id was passed.
|
214
|
+
# - *:parallel* : Utilizes parrallel HTTP requests to fetch all objects requested.
|
215
|
+
# - *:batch* : This uses a batch fetch request using a contained_in clause.
|
216
|
+
# @param compact [Boolean] whether to remove nil items from the returned array for objects
|
217
|
+
# that were not found.
|
218
|
+
# @return [Parse::Object] if only one id was provided as a parameter.
|
219
|
+
# @return [Array<Parse::Object>] if more than one id was provided as a parameter.
|
134
220
|
def find(*parse_ids, type: :parallel, compact: true)
|
135
221
|
# flatten the list of Object ids.
|
136
222
|
parse_ids.flatten!
|
@@ -160,8 +246,6 @@ module Parse
|
|
160
246
|
as_array ? results : results.first
|
161
247
|
end; alias_method :get, :find
|
162
248
|
|
163
|
-
end # ClassMethods
|
164
|
-
|
165
249
|
end # Querying
|
166
250
|
|
167
251
|
|
@@ -4,24 +4,12 @@
|
|
4
4
|
require_relative "properties"
|
5
5
|
|
6
6
|
module Parse
|
7
|
-
#
|
8
|
-
def self.auto_upgrade!
|
9
|
-
klassModels = Parse::Object.descendants
|
10
|
-
klassModels.sort_by { |c| c.parse_class }.each do |klass|
|
11
|
-
yield(klass) if block_given?
|
12
|
-
klass.auto_upgrade!
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
7
|
+
# Defines the Schema methods applied to a Parse::Object.
|
16
8
|
module Schema
|
17
9
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
module ClassMethods
|
23
|
-
|
24
|
-
# returns the schema of the defined class in the Parse JSON format.
|
10
|
+
# Generate a Parse-server compatible schema hash for performing changes to the
|
11
|
+
# structure of the remote collection.
|
12
|
+
# @return [Hash] the schema for this Parse::Object subclass.
|
25
13
|
def schema
|
26
14
|
sch = { className: parse_class, fields: {} }
|
27
15
|
#first go through all the attributes
|
@@ -54,25 +42,36 @@ module Parse
|
|
54
42
|
sch
|
55
43
|
end
|
56
44
|
|
57
|
-
#
|
45
|
+
# Update the remote schema for this Parse collection.
|
46
|
+
# @param schema_updates [Hash] the changes to be made to the schema.
|
47
|
+
# @return [Parse::Response]
|
58
48
|
def update_schema(schema_updates = nil)
|
59
49
|
schema_updates ||= schema
|
60
50
|
client.update_schema parse_class, schema_updates
|
61
51
|
end
|
62
52
|
|
53
|
+
# Create a new collection for this model with the schema defined by the local
|
54
|
+
# model.
|
55
|
+
# @return [Parse::Response]
|
56
|
+
# @see Schema.schema
|
63
57
|
def create_schema
|
64
58
|
client.create_schema parse_class, schema
|
65
59
|
end
|
66
60
|
|
67
|
-
#
|
61
|
+
# Fetche the current schema for this collection from Parse server.
|
62
|
+
# @return [Parse::Response]
|
68
63
|
def fetch_schema
|
69
64
|
client.schema parse_class
|
70
65
|
end
|
71
66
|
|
72
|
-
# A class method for non-destructive auto upgrading a remote schema based
|
73
|
-
# and relations you have defined
|
74
|
-
#
|
75
|
-
#
|
67
|
+
# A class method for non-destructive auto upgrading a remote schema based
|
68
|
+
# on the properties and relations you have defined in your local model. If
|
69
|
+
# the collection doesn't exist, we create the schema. If the collection already
|
70
|
+
# exists, the current schema is fetched, and only add the additional fields
|
71
|
+
# that are missing.
|
72
|
+
# @note No columns or fields are removed, this is a safe non-destructive upgrade.
|
73
|
+
# @return [Parse::Response] if the remote schema was modified.
|
74
|
+
# @return [Boolean] if no changes were made to the schema, it returns true.
|
76
75
|
def auto_upgrade!
|
77
76
|
response = fetch_schema
|
78
77
|
if response.success?
|
@@ -86,18 +85,9 @@ module Parse
|
|
86
85
|
end
|
87
86
|
return true if current_schema[:fields].empty?
|
88
87
|
return update_schema( current_schema )
|
89
|
-
else
|
90
|
-
return create_schema
|
91
88
|
end
|
92
|
-
|
89
|
+
create_schema
|
93
90
|
end
|
94
|
-
#def diff(h2);self.dup.delete_if { |k, v| h2[k] == v }.merge(h2.dup.delete_if { |k, v| self.has_key?(k) }); end;
|
95
|
-
|
96
|
-
end
|
97
|
-
|
98
|
-
def schema
|
99
|
-
self.class.schema
|
100
|
-
end
|
101
91
|
|
102
92
|
end
|
103
93
|
end
|
data/lib/parse/model/object.rb
CHANGED
@@ -21,6 +21,7 @@ require_relative "date"
|
|
21
21
|
require_relative "acl"
|
22
22
|
require_relative "push"
|
23
23
|
require_relative 'core/actions'
|
24
|
+
require_relative 'core/fetching'
|
24
25
|
require_relative 'core/querying'
|
25
26
|
require_relative "core/schema"
|
26
27
|
require_relative "core/properties"
|
@@ -32,7 +33,17 @@ require_relative "associations/has_many"
|
|
32
33
|
module Parse
|
33
34
|
# @return [Array] an array of registered Parse::Object subclasses.
|
34
35
|
def self.registered_classes
|
35
|
-
Parse::Object.descendants.map
|
36
|
+
Parse::Object.descendants.map(&:parse_class).uniq
|
37
|
+
end
|
38
|
+
|
39
|
+
# Perform a non-destructive upgrade of all your Parse schemas in the backend
|
40
|
+
# based on the property definitions of your local {Parse::Object} subclasses.
|
41
|
+
def self.auto_upgrade!
|
42
|
+
klassModels = Parse::Object.descendants
|
43
|
+
klassModels.sort_by(&:parse_class).each do |klass|
|
44
|
+
yield(klass) if block_given?
|
45
|
+
klass.auto_upgrade!
|
46
|
+
end
|
36
47
|
end
|
37
48
|
|
38
49
|
# This is the core class for all app specific Parse table subclasses. This class
|
@@ -53,10 +64,8 @@ module Parse
|
|
53
64
|
# Properties:
|
54
65
|
#
|
55
66
|
# All columns in a Parse object are considered a type of property (ex. string, numbers, arrays, etc)
|
56
|
-
# except in two cases - Pointers and Relations. For
|
57
|
-
#
|
58
|
-
# dynamic methods are created that take advantage of all the ActiveModel
|
59
|
-
# plugins (dirty tracking, callbacks, json, etc).
|
67
|
+
# except in two cases - Pointers and Relations. For a detailed discussion of properties, see
|
68
|
+
# The {https://github.com/modernistik/parse-stack#defining-properties Defining Properties} section.
|
60
69
|
#
|
61
70
|
# Associations:
|
62
71
|
#
|
@@ -74,27 +83,18 @@ module Parse
|
|
74
83
|
# without requiring an explicit intermediary Parse table or class. This feature
|
75
84
|
# is also implemented using the `:has_many` method but passing the option of `:relation`.
|
76
85
|
#
|
77
|
-
#
|
78
|
-
#
|
79
|
-
#
|
80
|
-
# Parse table.
|
81
|
-
#
|
82
|
-
# Fetching:
|
83
|
-
# The fetching modules supports fetching data from Parse (depending on the state of the object),
|
84
|
-
# and providing some autofetching features when traversing relational objects and properties.
|
85
|
-
#
|
86
|
-
# Schema:
|
87
|
-
# The schema module provides methods to modify the Parse table remotely to either add or create
|
88
|
-
# any locally define properties in ruby and have those be reflected in the Parse application.
|
86
|
+
# @see Associations::BelongsTo
|
87
|
+
# @see Associations::HasOne
|
88
|
+
# @see Associations::HasMany
|
89
89
|
class Object < Pointer
|
90
90
|
include Properties
|
91
91
|
include Associations::HasOne
|
92
92
|
include Associations::BelongsTo
|
93
93
|
include Associations::HasMany
|
94
|
-
|
94
|
+
extend Querying
|
95
|
+
extend Schema
|
95
96
|
include Fetching
|
96
97
|
include Actions
|
97
|
-
include Schema
|
98
98
|
BASE_OBJECT_CLASS = "Parse::Object".freeze
|
99
99
|
|
100
100
|
# @return [Model::TYPE_OBJECT]
|
@@ -145,7 +145,7 @@ module Parse
|
|
145
145
|
|
146
146
|
attr_accessor :disable_serialized_string_date, :parse_class, :acl
|
147
147
|
|
148
|
-
# @!attribute
|
148
|
+
# @!attribute disable_serialized_string_date
|
149
149
|
# Disables returning a serialized string date properties when encoding to JSON.
|
150
150
|
# This affects created_at and updated_at fields in order to be backwards compatible with old SDKs.
|
151
151
|
# @return [Boolean]
|
@@ -191,6 +191,12 @@ module Parse
|
|
191
191
|
end
|
192
192
|
alias_method :className, :parse_class
|
193
193
|
|
194
|
+
# @return [Hash] the schema structure for this Parse collection from the server.
|
195
|
+
# @see Parse::Schema
|
196
|
+
def schema
|
197
|
+
self.class.schema
|
198
|
+
end
|
199
|
+
|
194
200
|
# @return [Hash] a json-hash representing this object.
|
195
201
|
def as_json(*args)
|
196
202
|
pointer? ? pointer : super(*args)
|
data/lib/parse/model/pointer.rb
CHANGED
@@ -65,6 +65,7 @@ module Parse
|
|
65
65
|
#
|
66
66
|
# @see Parse::Object
|
67
67
|
class Pointer < Model
|
68
|
+
# Attributes of a Pointer.
|
68
69
|
ATTRIBUTES = { __type: :string, className: :string, objectId: :string}.freeze
|
69
70
|
# @return [String] the name of the Parse class for this pointer.
|
70
71
|
attr_accessor :parse_class
|
@@ -3,23 +3,35 @@
|
|
3
3
|
|
4
4
|
require_relative 'operation'
|
5
5
|
require 'time'
|
6
|
-
|
7
|
-
# Each constraint is made up of an Operation and a value (the right side
|
8
|
-
# of an operator). Constraints are responsible for making their specific
|
9
|
-
# Parse hash format required when sending Queries to Parse. All constraints can
|
10
|
-
# be combined by merging different constraints (since they are multiple hashes)
|
11
|
-
# and some constraints may have higher precedence than others (ex. equality is higher
|
12
|
-
# precedence than an "in" query).
|
13
|
-
# All constraints should inherit from Parse::Constraint and should
|
14
|
-
# register their specific Operation method (ex. :eq or :lte)
|
15
|
-
# For more information about the query design pattern from DataMapper
|
16
|
-
# that inspired this, see http://datamapper.org/docs/find.html
|
6
|
+
|
17
7
|
module Parse
|
8
|
+
# Constraints are the heart of the Parse::Query system.
|
9
|
+
# Each constraint is made up of an Operation and a value (the right side
|
10
|
+
# of an operator). Constraints are responsible for making their specific
|
11
|
+
# Parse hash format required when sending Queries to Parse. All constraints can
|
12
|
+
# be combined by merging different constraints (since they are multiple hashes)
|
13
|
+
# and some constraints may have higher precedence than others (ex. equality is higher
|
14
|
+
# precedence than an "in" query).
|
15
|
+
# All constraints should inherit from Parse::Constraint and should
|
16
|
+
# register their specific Operation method (ex. :eq or :lte)
|
17
|
+
# For more information about the query design pattern from DataMapper
|
18
|
+
# that inspired this, see http://datamapper.org/docs/find.html
|
18
19
|
class Constraint
|
19
20
|
|
21
|
+
# @!attribute operation
|
22
|
+
# The operation tied to this constraint.
|
23
|
+
# @return [Parse::Operation]
|
24
|
+
|
25
|
+
# @!attribute value
|
26
|
+
# The value to be applied to this constraint.
|
27
|
+
# @return [Parse::Operation]
|
28
|
+
|
20
29
|
attr_accessor :operation, :value
|
21
|
-
|
22
|
-
#
|
30
|
+
|
31
|
+
# Create a new constraint.
|
32
|
+
# @param operation [Parse::Operation] the operation for this constraint.
|
33
|
+
# @param value [Object] the value to attach to this constraint.
|
34
|
+
# @yield You may also pass a block to modify the operation or value.
|
23
35
|
def initialize(operation, value)
|
24
36
|
# if the first parameter is not an Operation, but it is a symbol
|
25
37
|
# it most likely is just the field name, so let's assume they want
|
@@ -34,16 +46,22 @@ module Parse
|
|
34
46
|
end
|
35
47
|
|
36
48
|
class << self
|
49
|
+
# @!attribute key
|
37
50
|
# The class attributes keep track of the Parse key (special Parse
|
38
51
|
# text symbol representing this operation. Ex. local method could be called
|
39
52
|
# .ex, where the Parse Query operation that should be sent out is "$exists")
|
40
53
|
# in this case, key should be set to "$exists"
|
54
|
+
# @return [Symbol]
|
41
55
|
attr_accessor :key
|
56
|
+
|
57
|
+
# @!attribute precedence
|
42
58
|
# Precedence defines the priority of this operation when merging.
|
43
59
|
# The higher the more priority it will receive.
|
60
|
+
# @return [Integer]
|
44
61
|
attr_accessor :precedence
|
45
62
|
|
46
|
-
#
|
63
|
+
# @!attribute operand
|
64
|
+
# @return [Symbol] the operand for this constraint.
|
47
65
|
attr_accessor :operand
|
48
66
|
|
49
67
|
# Creates a new constraint given an operation and value.
|
@@ -55,24 +73,33 @@ module Parse
|
|
55
73
|
operation.constraint(value)
|
56
74
|
end
|
57
75
|
|
58
|
-
#
|
59
|
-
|
60
|
-
|
76
|
+
# Set the keyword for this Constaint. Subclasses should use this method.
|
77
|
+
# @param keyword [Symbol]
|
78
|
+
# @return (see key)
|
79
|
+
def contraint_keyword(keyword)
|
80
|
+
@key = keyword
|
61
81
|
end
|
62
82
|
|
63
|
-
|
83
|
+
# Set the default precedence for this constraint.
|
84
|
+
# @param priority [Integer] a higher priority has higher precedence
|
85
|
+
# @return [Integer]
|
86
|
+
def precedence(priority = nil)
|
64
87
|
@precedence = 0 if @precedence.nil?
|
65
|
-
@precedence =
|
88
|
+
@precedence = priority unless priority.nil?
|
66
89
|
@precedence
|
67
90
|
end
|
68
91
|
|
69
|
-
#
|
70
|
-
#
|
92
|
+
# Register the given operand for this Parse::Constraint subclass.
|
93
|
+
# @note All subclasses should register their operation and themselves.
|
94
|
+
# @param op [Symbol] the operand
|
95
|
+
# @param klass [Parse::Constraint] a subclass of Parse::Constraint
|
96
|
+
# @return (see Parse::Operation.register)
|
71
97
|
def register(op, klass = self)
|
72
98
|
self.operand ||= op
|
73
99
|
Operation.register op, klass
|
74
100
|
end
|
75
101
|
|
102
|
+
# @return [Object] a formatted value based on the data type.
|
76
103
|
def formatted_value(value)
|
77
104
|
d = value
|
78
105
|
d = { __type: "Date", iso: d.utc.iso8601(3) } if d.respond_to?(:utc)
|
@@ -91,21 +118,28 @@ module Parse
|
|
91
118
|
|
92
119
|
end
|
93
120
|
|
121
|
+
# @return [Integer] the precedence of this constraint
|
94
122
|
def precedence
|
95
123
|
self.class.precedence
|
96
124
|
end
|
97
125
|
|
126
|
+
# @return [Symbol] the Parse keyword for this constraint.
|
98
127
|
def key
|
99
128
|
self.class.key
|
100
129
|
end
|
101
130
|
|
131
|
+
# @!attribute operand
|
132
|
+
# @return [Symbol] the operand for the operation.
|
102
133
|
def operand
|
103
134
|
@operation.operand unless @operation.nil?
|
104
135
|
end
|
136
|
+
|
105
137
|
def operand=(o)
|
106
138
|
@operation.operand = o unless @operation.nil?
|
107
139
|
end
|
108
140
|
|
141
|
+
# @!attribute operator
|
142
|
+
# @return [Symbol] the operator for the operation.
|
109
143
|
def operator
|
110
144
|
@operation.operator unless @operation.nil?
|
111
145
|
end
|
@@ -114,33 +148,37 @@ module Parse
|
|
114
148
|
@operation.operator = o unless @operation.nil?
|
115
149
|
end
|
116
150
|
|
151
|
+
# @!visibility private
|
117
152
|
def inspect
|
118
153
|
"<#{self.class} #{operator.to_s}(#{operand.inspect}, `#{value}`)>"
|
119
154
|
end
|
120
155
|
|
156
|
+
# Calls build internally
|
157
|
+
# @return [Hash]
|
121
158
|
def as_json(*args)
|
122
159
|
build
|
123
160
|
end
|
124
161
|
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
129
|
-
# we need to format the value for particular data types.
|
162
|
+
# Builds the JSON hash representation of this constraint for a Parse query.
|
163
|
+
# This method should be overriden by subclasses. The default implementation
|
164
|
+
# implements buildling the equality constraint.
|
165
|
+
# @return [Hash]
|
130
166
|
def build
|
131
167
|
return { @operation.operand => formatted_value } if @operation.operator == :eq || key.nil?
|
132
168
|
{ @operation.operand => { key => formatted_value } }
|
133
169
|
end
|
134
170
|
|
171
|
+
# @return [String] string representation of this constraint.
|
135
172
|
def to_s
|
136
173
|
inspect
|
137
174
|
end
|
138
175
|
|
139
|
-
#
|
176
|
+
# @return [Object] formatted value based on the specific data type.
|
140
177
|
def formatted_value
|
141
178
|
self.class.formatted_value(@value)
|
142
179
|
end
|
143
180
|
|
181
|
+
# Registers the default constraint of equality
|
144
182
|
register :eq, Constraint
|
145
183
|
precedence 100
|
146
184
|
end
|
@@ -11,9 +11,6 @@ require_relative 'constraint'
|
|
11
11
|
# For more information about the query design pattern from DataMapper
|
12
12
|
# that inspired this, see http://datamapper.org/docs/find.html
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
14
|
module Parse
|
18
15
|
# Error for when there is a problem with the input passed to a constraint.
|
19
16
|
class ConstraintError < StandardError; end;
|