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
@@ -19,4 +19,51 @@ module Parse
|
|
19
19
|
CONTENT_TYPE_FORMAT = 'application/json; charset=utf-8'
|
20
20
|
end
|
21
21
|
|
22
|
+
module ErrorCodes
|
23
|
+
# OtherCause -1 Error code indicating that an unknown error or an error unrelated to Parse occurred.
|
24
|
+
# InternalServerError 1 Error code indicating that something has gone wrong with the server. If you get this error code, it is Parse's fault. Please report the bug to https://parse.com/help.
|
25
|
+
# ConnectionFailed 100 Error code indicating the connection to the Parse servers failed.
|
26
|
+
# ObjectNotFound 101 Error code indicating the specified object doesn't exist.
|
27
|
+
# InvalidQuery 102 Error code indicating you tried to query with a datatype that doesn't support it, like exact matching an array or object.
|
28
|
+
# InvalidClassName 103 Error code indicating a missing or invalid classname. Classnames are case-sensitive. They must start with a letter, and a-zA-Z0-9_ are the only valid characters.
|
29
|
+
# MissingObjectId 104 Error code indicating an unspecified object id.
|
30
|
+
# InvalidKeyName 105 Error code indicating an invalid key name. Keys are case-sensitive. They must start with a letter, and a-zA-Z0-9_ are the only valid characters.
|
31
|
+
# InvalidPointer 106 Error code indicating a malformed pointer. You should not see this unless you have been mucking about changing internal Parse code.
|
32
|
+
# InvalidJSON 107 Error code indicating that badly formed JSON was received upstream. This either indicates you have done something unusual with modifying how things encode to JSON, or the network is failing badly.
|
33
|
+
# CommandUnavailable 108 Error code indicating that the feature you tried to access is only available internally for testing purposes.
|
34
|
+
# NotInitialized 109 You must call Parse.initialize before using the Parse library.
|
35
|
+
# IncorrectType 111 Error code indicating that a field was set to an inconsistent type.
|
36
|
+
# InvalidChannelName 112 Error code indicating an invalid channel name. A channel name is either an empty string (the broadcast channel) or contains only a-zA-Z0-9_ characters and starts with a letter.
|
37
|
+
# PushMisconfigured 115 Error code indicating that push is misconfigured.
|
38
|
+
# ObjectTooLarge 116 Error code indicating that the object is too large.
|
39
|
+
# OperationForbidden 119 Error code indicating that the operation isn't allowed for clients.
|
40
|
+
# CacheMiss 120 Error code indicating the result was not found in the cache.
|
41
|
+
# InvalidNestedKey 121 Error code indicating that an invalid key was used in a nested JSONObject.
|
42
|
+
# InvalidFileName 122 Error code indicating that an invalid filename was used for ParseFile. A valid file name contains only a-zA-Z0-9_. characters and is between 1 and 128 characters.
|
43
|
+
# InvalidACL 123 Error code indicating an invalid ACL was provided.
|
44
|
+
# Timeout 124 Error code indicating that the request timed out on the server. Typically this indicates that the request is too expensive to run.
|
45
|
+
# InvalidEmailAddress 125 Error code indicating that the email address was invalid.
|
46
|
+
# DuplicateValue 137 Error code indicating that a unique field was given a value that is already taken.
|
47
|
+
# InvalidRoleName 139 Error code indicating that a role's name is invalid.
|
48
|
+
# ExceededQuota 140 Error code indicating that an application quota was exceeded. Upgrade to resolve.
|
49
|
+
# ScriptFailed 141 Error code indicating that a Cloud Code script failed.
|
50
|
+
# ValidationFailed 142 Error code indicating that a Cloud Code validation failed.
|
51
|
+
# FileDeleteFailed 153 Error code indicating that deleting a file failed.
|
52
|
+
# RequestLimitExceeded 155 Error code indicating that the application has exceeded its request limit.
|
53
|
+
# InvalidEventName 160 Error code indicating that the provided event name is invalid.
|
54
|
+
# UsernameMissing 200 Error code indicating that the username is missing or empty.
|
55
|
+
# PasswordMissing 201 Error code indicating that the password is missing or empty.
|
56
|
+
# UsernameTaken 202 Error code indicating that the username has already been taken.
|
57
|
+
# EmailTaken 203 Error code indicating that the email has already been taken.
|
58
|
+
# EmailMissing 204 Error code indicating that the email is missing, but must be specified.
|
59
|
+
# EmailNotFound 205 Error code indicating that a user with the specified email was not found.
|
60
|
+
# SessionMissing 206 Error code indicating that a user object without a valid session could not be altered.
|
61
|
+
# MustCreateUserThroughSignup 207 Error code indicating that a user can only be created through signup.
|
62
|
+
# AccountAlreadyLinked 208 Error code indicating that an an account being linked is already linked to another user.
|
63
|
+
# InvalidSessionToken 209 Error code indicating that the current session token is invalid.
|
64
|
+
# LinkedIdMissing 250 Error code indicating that a user cannot be linked to an account because that account's id could not be found.
|
65
|
+
# InvalidLinkedSession 251 Error code indicating that a user with a linked (e.g. Facebook) account has an invalid session.
|
66
|
+
# UnsupportedService 252 Error code indicating that a service being linked (e.g. Facebook or Twitter) is unsupported.
|
67
|
+
end
|
68
|
+
|
22
69
|
end
|
data/lib/parse/client/request.rb
CHANGED
@@ -5,52 +5,81 @@ require 'active_support'
|
|
5
5
|
require 'active_support/json'
|
6
6
|
|
7
7
|
module Parse
|
8
|
-
|
9
|
-
|
8
|
+
#This class represents a Parse request.
|
10
9
|
class Request
|
11
|
-
|
12
|
-
|
13
|
-
def initialize(method, uri, body: nil, headers: nil, opts: {})
|
14
|
-
@tag = 0
|
15
|
-
method = method.downcase.to_sym
|
16
|
-
unless method == :get || method == :put || method == :post || method == :delete
|
17
|
-
raise ArgumentError, "Invalid method #{method} for request : '#{uri}'"
|
18
|
-
end
|
19
|
-
self.method = method
|
20
|
-
self.path = uri
|
21
|
-
self.body = body
|
22
|
-
self.headers = headers || {}
|
23
|
-
self.opts = opts || {}
|
24
|
-
end
|
10
|
+
# @!attribute [rw] method
|
11
|
+
# @return [String] the HTTP method used for this request.
|
25
12
|
|
13
|
+
# @!attribute [rw] path
|
14
|
+
# @return [String] the uri path.
|
26
15
|
|
27
|
-
|
28
|
-
|
29
|
-
end
|
16
|
+
# @!attribute [rw] body
|
17
|
+
# @return [Hash] the body of this request.
|
30
18
|
|
31
|
-
|
32
|
-
signature.as_json
|
33
|
-
end
|
19
|
+
# TODO: Document opts and cache options.
|
34
20
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
21
|
+
# @!attribute [rw] opts
|
22
|
+
# @return [Hash] a set of options for this request.
|
23
|
+
# @!attribute [rw] cache
|
24
|
+
# @return [Boolean]
|
25
|
+
attr_accessor :method, :path, :body, :headers, :opts, :cache
|
39
26
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
def signature
|
44
|
-
{method: @method.upcase, path: @path, body: @body}
|
45
|
-
end
|
27
|
+
# @!visibility private
|
28
|
+
# Used to correlate batching requests with their responses.
|
29
|
+
attr_accessor :tag
|
46
30
|
|
47
|
-
|
48
|
-
|
31
|
+
# Creates a new request
|
32
|
+
# @param method [String] the HTTP method
|
33
|
+
# @param uri [String] the API path of the request (without the host)
|
34
|
+
# @param body [Hash] the body (or parameters) of this request.
|
35
|
+
# @param headers [Hash] additional headers to send in this request.
|
36
|
+
# @param opts [Hash] additional optional parameters.
|
37
|
+
def initialize(method, uri, body: nil, headers: nil, opts: {})
|
38
|
+
@tag = 0
|
39
|
+
method = method.downcase.to_sym
|
40
|
+
unless method == :get || method == :put || method == :post || method == :delete
|
41
|
+
raise ArgumentError, "Invalid method #{method} for request : '#{uri}'"
|
49
42
|
end
|
43
|
+
self.method = method
|
44
|
+
self.path = uri
|
45
|
+
self.body = body
|
46
|
+
self.headers = headers || {}
|
47
|
+
self.opts = opts || {}
|
48
|
+
end
|
50
49
|
|
51
|
-
|
52
|
-
|
53
|
-
|
50
|
+
# The parameters of this request if the HTTP method is GET.
|
51
|
+
# @return [Hash]
|
52
|
+
def query
|
53
|
+
body if @method == :get
|
54
|
+
end
|
55
|
+
|
56
|
+
# @return [Hash] JSON encoded hash
|
57
|
+
def as_json
|
58
|
+
signature.as_json
|
59
|
+
end
|
60
|
+
|
61
|
+
# @return [Boolean]
|
62
|
+
def ==(r)
|
63
|
+
return false unless r.is_a?(Request)
|
64
|
+
@method == r.method && @path == r.uri && @body == r.body && @headers == r.headers
|
65
|
+
end
|
66
|
+
|
67
|
+
# Signature provies a way for us to compare different requests objects.
|
68
|
+
# Two requests objects are the same if they have the same signature.
|
69
|
+
# @return [Hash] A hash representing this request.
|
70
|
+
def signature
|
71
|
+
{method: @method.upcase, path: @path, body: @body}
|
72
|
+
end
|
73
|
+
|
74
|
+
# @!visibility private
|
75
|
+
def inspect
|
76
|
+
"#<#{self.class} @method=#{@method} @path='#{@path}'>"
|
77
|
+
end
|
78
|
+
|
79
|
+
# @return [String]
|
80
|
+
def to_s
|
81
|
+
"#{@method.to_s.upcase} #{@path}"
|
82
|
+
end
|
54
83
|
|
55
84
|
end
|
56
85
|
|
@@ -53,7 +53,7 @@ require 'active_support/json'
|
|
53
53
|
# be a set of responses (from a Batch response).
|
54
54
|
module Parse
|
55
55
|
|
56
|
-
|
56
|
+
class ResponseError < StandardError; end;
|
57
57
|
class Response
|
58
58
|
include Enumerable
|
59
59
|
|
@@ -66,18 +66,36 @@ module Parse
|
|
66
66
|
ERROR_PASSWORD_MISSING = 201
|
67
67
|
ERROR_USERNAME_TAKEN = 202
|
68
68
|
ERROR_EMAIL_TAKEN = 203
|
69
|
+
ERROR_EMAIL_NOT_FOUND = 205
|
70
|
+
ERROR_EMAIL_INVALID = 125
|
69
71
|
|
70
72
|
ERROR = "error"
|
71
73
|
CODE = "code"
|
72
74
|
RESULTS = "results"
|
73
75
|
COUNT = "count"
|
74
|
-
|
75
|
-
|
76
|
-
|
76
|
+
|
77
|
+
# @!attribute [rw] parse_class
|
78
|
+
# @return [String] the Parse class for this request
|
79
|
+
# @!attribute [rw] code
|
80
|
+
# @return [Integer] the error code
|
81
|
+
# @!attribute [rw] error
|
82
|
+
# @return [Integer] the error message
|
83
|
+
# @!attribute [rw] result
|
84
|
+
# @return [Hash] the body of the response result.
|
85
|
+
# @!attribute [rw] http_status
|
86
|
+
# @return [Integer] the HTTP status code from the response.
|
87
|
+
# @!attribute [rw] request
|
88
|
+
# @return [Integer] the Parse::Request that generated this response.
|
89
|
+
# @see Parse::Request
|
90
|
+
attr_accessor :parse_class, :code, :error, :result, :http_status,
|
91
|
+
:request
|
77
92
|
# You can query Parse for counting objects, which may not actually have
|
78
93
|
# results.
|
94
|
+
# @return [Integer] the count result from a count query request.
|
79
95
|
attr_reader :count
|
80
96
|
|
97
|
+
# Create an instance with a Parse response JSON hash.
|
98
|
+
# @param res [Hash] the JSON hash
|
81
99
|
def initialize(res = {})
|
82
100
|
@http_status = 0
|
83
101
|
@count = 0
|
@@ -86,7 +104,7 @@ module Parse
|
|
86
104
|
# If a string is used for initializing, treat it as JSON
|
87
105
|
res = JSON.parse(res) if res.is_a?(String)
|
88
106
|
# If it is a hash (or parsed JSON), then parse the result.
|
89
|
-
parse_result(res) if res.is_a?(Hash)
|
107
|
+
parse_result!(res) if res.is_a?(Hash)
|
90
108
|
# if the result is an Array, then most likely it is a set of responses
|
91
109
|
# from using a Batch API.
|
92
110
|
if res.is_a?(Array)
|
@@ -99,21 +117,14 @@ module Parse
|
|
99
117
|
|
100
118
|
end
|
101
119
|
|
120
|
+
# true if this was a batch response.
|
102
121
|
def batch?
|
103
122
|
@batch_response
|
104
123
|
end
|
105
|
-
|
106
|
-
#
|
107
|
-
# [
|
108
|
-
# {
|
109
|
-
# "success":{"createdAt":"2015-11-22T19:04:16.104Z","objectId":"s4tEzOVQFc"}
|
110
|
-
# },
|
111
|
-
# {
|
112
|
-
# "error":{"code":101,"error":"object not found for update"}
|
113
|
-
# }
|
114
|
-
# ]
|
124
|
+
|
115
125
|
# If it is a batch respnose, we'll create an array of Response objects for each
|
116
126
|
# of the ones in the batch.
|
127
|
+
# @return [Array] an array of Response objects.
|
117
128
|
def batch_responses
|
118
129
|
|
119
130
|
return [@result] unless @batch_response
|
@@ -128,8 +139,7 @@ module Parse
|
|
128
139
|
# This method takes the result hash and determines if it is a regular
|
129
140
|
# parse query result, object result or a count result. The response should
|
130
141
|
# be a hash either containing the result data or the error.
|
131
|
-
|
132
|
-
def parse_result(h)
|
142
|
+
def parse_result!(h)
|
133
143
|
@result = {}
|
134
144
|
return unless h.is_a?(Hash)
|
135
145
|
@code = h[CODE]
|
@@ -143,31 +153,38 @@ module Parse
|
|
143
153
|
end
|
144
154
|
|
145
155
|
end
|
156
|
+
alias_method :parse_results!, :parse_result!
|
146
157
|
|
147
|
-
#
|
158
|
+
# true if the response is successful.
|
159
|
+
# @see #error?
|
148
160
|
def success?
|
149
161
|
@code.nil? && @error.nil?
|
150
162
|
end
|
151
163
|
|
164
|
+
# true if the response has an error code.
|
165
|
+
# @see #success?
|
152
166
|
def error?
|
153
167
|
! success?
|
154
168
|
end
|
155
169
|
|
170
|
+
# true if the response has an error code of 'object not found'
|
171
|
+
# @see ERROR_OBJECT_NOT_FOUND
|
156
172
|
def object_not_found?
|
157
173
|
@code == ERROR_OBJECT_NOT_FOUND
|
158
174
|
end
|
159
175
|
|
160
|
-
#
|
176
|
+
# @return [Array] the result data from the response.
|
161
177
|
def results
|
162
178
|
return [] if @result.nil?
|
163
179
|
@result.is_a?(Array) ? @result : [@result]
|
164
180
|
end
|
165
181
|
|
166
|
-
#
|
182
|
+
# @return [Object] the first thing in the result array.
|
167
183
|
def first
|
168
184
|
@result.is_a?(Array) ? @result.first : @result
|
169
185
|
end
|
170
|
-
|
186
|
+
# Iterate through each result item.
|
187
|
+
# @yieldparam [Object] a result entry.
|
171
188
|
def each
|
172
189
|
return enum_for(:each) unless block_given?
|
173
190
|
results.each(&Proc.new)
|
@@ -182,6 +199,7 @@ module Parse
|
|
182
199
|
end
|
183
200
|
end
|
184
201
|
|
202
|
+
# @return [String] JSON encoded object, or an error string.
|
185
203
|
def to_s
|
186
204
|
return "[E-#{@code}] #{@request} : #{@error} (#{@http_status})" if error?
|
187
205
|
@result.to_json
|
data/lib/parse/model/acl.rb
CHANGED
@@ -12,9 +12,9 @@
|
|
12
12
|
# JSON structure.
|
13
13
|
# The class below also implements a type of delegate pattern in order to inform the main Parse::Object
|
14
14
|
# of dirty tracking.
|
15
|
+
|
15
16
|
module Parse
|
16
17
|
|
17
|
-
# Base class for supporting custom data types
|
18
18
|
class DataType
|
19
19
|
include ::ActiveModel::Model
|
20
20
|
include ::ActiveModel::Serializers::JSON
|
@@ -33,12 +33,10 @@ module Parse
|
|
33
33
|
end
|
34
34
|
|
35
35
|
class ACL < DataType
|
36
|
-
|
36
|
+
|
37
37
|
attr_accessor :permissions, :delegate
|
38
|
-
PUBLIC = "*"
|
38
|
+
PUBLIC = "*"
|
39
39
|
|
40
|
-
# provide a set of acls and the delegate (for dirty tracking)
|
41
|
-
# { '*' => { "read": true, "write": true } }
|
42
40
|
def initialize(acls = {}, owner: nil)
|
43
41
|
everyone(true, true) # sets Public read/write
|
44
42
|
@delegate = owner
|
@@ -48,7 +46,6 @@ module Parse
|
|
48
46
|
|
49
47
|
end
|
50
48
|
|
51
|
-
# helper
|
52
49
|
def self.permission(read, write = nil)
|
53
50
|
ACL::Permission.new(read, write)
|
54
51
|
end
|
@@ -63,15 +60,13 @@ module Parse
|
|
63
60
|
permissions.keys.all? { |per| permissions[per] == other_acl.permissions[per] }
|
64
61
|
end
|
65
62
|
|
66
|
-
# method to set the Public read/write priviledges ('*'). Alias is 'world'
|
67
63
|
def everyone(read, write)
|
68
64
|
apply(PUBLIC, read, write)
|
69
65
|
permissions[PUBLIC]
|
70
66
|
end
|
71
67
|
alias_method :world, :everyone
|
72
68
|
|
73
|
-
# dirty tracking. We will tell the delegate through the acl_will_change!
|
74
|
-
# method
|
69
|
+
# dirty tracking. We will tell the delegate through the acl_will_change! method
|
75
70
|
def will_change!
|
76
71
|
@delegate.acl_will_change! if @delegate.respond_to?(:acl_will_change!)
|
77
72
|
end
|
@@ -6,20 +6,111 @@ require_relative 'collection_proxy'
|
|
6
6
|
require_relative 'pointer_collection_proxy'
|
7
7
|
require_relative 'relation_collection_proxy'
|
8
8
|
|
9
|
-
|
10
|
-
# table constains a column that points to a foreign table record using
|
11
|
-
# a given Parse Pointer. The key of the property is implied to be the
|
12
|
-
# name of the class/parse table that contains the foreign associated record.
|
13
|
-
# All belongs to relationship column types have the special data type of :pointer.
|
9
|
+
|
14
10
|
module Parse
|
15
11
|
module Associations
|
16
|
-
|
12
|
+
# This association creates a one-to-one association with another Parse model.
|
13
|
+
# BelongsTo relation is the simplies association in which the local
|
14
|
+
# Parse table constains a column that has a Parse::Pointer to a foreign table record.
|
15
|
+
#
|
16
|
+
# This association says that this class contains a foreign pointer column
|
17
|
+
# which references a different class. Utilizing the `belongs_to` method in
|
18
|
+
# defining a property in a Parse::Object subclass sets up an association
|
19
|
+
# between the local table and a foreign table. Specifying the `belongs_to`
|
20
|
+
# in the class, tells the framework that the Parse table contains a local
|
21
|
+
# column in its schema that has a reference to a record in a foreign table.
|
22
|
+
# The argument to `belongs_to` should be the singularized version of the
|
23
|
+
# foreign Parse::Object class. you should specify the foreign table as the
|
24
|
+
# snake_case singularized version of the foreign table class.
|
25
|
+
#
|
26
|
+
# Note that the reverse relationship on the foreign class is not generated automatically.
|
27
|
+
# You can use a `has_one` on the foreign model to create it.
|
28
|
+
# @example
|
29
|
+
# class Author < Parse::Object
|
30
|
+
# property :name
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
#
|
34
|
+
# class Post < Parse::Object
|
35
|
+
# belongs_to :author
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# Post.references # => {:author=>"Author"}
|
39
|
+
#
|
40
|
+
# post = Post.first
|
41
|
+
# post.author? # => true if has a pointer
|
42
|
+
#
|
43
|
+
# # Follow the author pointer and get name
|
44
|
+
# post.author.name
|
45
|
+
#
|
46
|
+
# other_author = Author.first
|
47
|
+
# # change author by setting new pointer
|
48
|
+
# post.author = other_author
|
49
|
+
# post.save
|
50
|
+
#
|
51
|
+
# @see Parse::Associations::HasOne
|
52
|
+
# @see Parse::Associations::HasMany
|
17
53
|
module BelongsTo
|
18
54
|
|
55
|
+
# @!attribute [rw] self.references
|
56
|
+
# A hash mapping of all belongs_to associations for this model.
|
57
|
+
# @return [Hash]
|
58
|
+
|
59
|
+
# @!method key?
|
60
|
+
# A dynamically generated method based on the value of `key` passed to the
|
61
|
+
# belongs_to method, which returns true if this instance has a pointer for
|
62
|
+
# this field.
|
63
|
+
# @example
|
64
|
+
#
|
65
|
+
# class Post < Parse::Object
|
66
|
+
# belongs_to :author # generates 'author?'
|
67
|
+
# end
|
68
|
+
#
|
69
|
+
# post = Post.new
|
70
|
+
# post.author? # => false
|
71
|
+
# post.author = Author.new
|
72
|
+
# post.author? # => true
|
73
|
+
# @return [Boolean] true if field contains a Parse::Pointer or subclass.
|
74
|
+
|
75
|
+
|
76
|
+
# @!method self.belongs_to(key, opts = {})
|
77
|
+
# Creates a one-to-one association with another Parse model.
|
78
|
+
# @param [Symbol] key The singularized version of the foreign class and the name of the
|
79
|
+
# local column in the remote Parse table where the pointer is stored.
|
80
|
+
# @option opts [Symbol] :field override the name of the remote column
|
81
|
+
# where the pointer is stored. By default this is inferred as
|
82
|
+
# the columnized of the key parameter.
|
83
|
+
# @option opts [Symbol] :as override the inferred Parse::Object subclass.
|
84
|
+
# By default this is inferred as the singularized camel case version of
|
85
|
+
# the key parameter. This option allows you to override the typecast of
|
86
|
+
# foreign Parse model of the association, while allowing you to have a
|
87
|
+
# different accessor name.
|
88
|
+
# @option opts [Boolean] :required Setting to `true`, automatically creates
|
89
|
+
# an ActiveModel validation of `validates_presence_of` for the
|
90
|
+
# association. This will not prevent the save, but affects the validation
|
91
|
+
# check when `valid?` is called on an instance. Default is false.
|
92
|
+
# @example
|
93
|
+
# # Assumes 'Artist' is foreign class.
|
94
|
+
# belongs_to :artist
|
95
|
+
#
|
96
|
+
# # uses Parse::User as foreign class
|
97
|
+
# belongs_to :manager, as: :user
|
98
|
+
#
|
99
|
+
# # sets attribute name to `featured_song` for foreign class Song with the remote
|
100
|
+
# # column name in Parse as 'theFeaturedSong'.
|
101
|
+
# belongs_to :featured_song, as: :song, field: :theFeaturedSong
|
102
|
+
#
|
103
|
+
# @see String#columnize
|
104
|
+
# @see #key?
|
105
|
+
# @return [Parse::Object] a Parse::Object subclass when using the accessor
|
106
|
+
# when fetching the association.
|
107
|
+
|
108
|
+
# @!visibility private
|
19
109
|
def self.included(base)
|
20
110
|
base.extend(ClassMethods)
|
21
111
|
end
|
22
112
|
|
113
|
+
# @!visibility private
|
23
114
|
module ClassMethods
|
24
115
|
attr_accessor :references
|
25
116
|
# We can keep references to all "belong_to" properties
|
@@ -27,9 +118,6 @@ module Parse
|
|
27
118
|
@references ||= {}
|
28
119
|
end
|
29
120
|
|
30
|
-
# belongs_to :featured_song, as: :song, field: :featuredSong, through: :reference
|
31
|
-
# belongs_to :artist
|
32
|
-
# belongs_to :manager, as: :user
|
33
121
|
# These items are added as attributes with the special data type of :pointer
|
34
122
|
def belongs_to(key, opts = {})
|
35
123
|
opts = {as: key, field: key.to_s.camelize(:lower), required: false}.merge(opts)
|