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