parse-stack 1.4.3 → 1.5.1
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 +52 -39
- data/Gemfile.lock +2 -2
- data/README.md +609 -124
- data/bin/console +0 -9
- data/lib/parse/api/all.rb +3 -0
- data/lib/parse/api/analytics.rb +2 -2
- data/lib/parse/api/apps.rb +15 -17
- data/lib/parse/api/batch.rb +4 -1
- data/lib/parse/api/cloud_functions.rb +2 -0
- data/lib/parse/api/config.rb +14 -2
- data/lib/parse/api/files.rb +6 -3
- data/lib/parse/api/hooks.rb +4 -4
- data/lib/parse/api/objects.rb +14 -11
- data/lib/parse/api/push.rb +4 -2
- data/lib/parse/api/schemas.rb +6 -5
- data/lib/parse/api/sessions.rb +11 -1
- data/lib/parse/api/users.rb +65 -15
- data/lib/parse/client/authentication.rb +4 -2
- data/lib/parse/client/body_builder.rb +11 -3
- data/lib/parse/client/caching.rb +17 -6
- data/lib/parse/client/protocol.rb +14 -8
- data/lib/parse/client/request.rb +4 -1
- data/lib/parse/client/response.rb +59 -6
- data/lib/parse/client.rb +72 -42
- data/lib/parse/model/acl.rb +22 -4
- data/lib/parse/model/associations/belongs_to.rb +22 -10
- data/lib/parse/model/associations/collection_proxy.rb +14 -1
- data/lib/parse/model/associations/has_many.rb +76 -15
- data/lib/parse/model/associations/has_one.rb +69 -0
- data/lib/parse/model/associations/pointer_collection_proxy.rb +13 -6
- data/lib/parse/model/associations/relation_collection_proxy.rb +5 -2
- data/lib/parse/model/bytes.rb +6 -2
- data/lib/parse/model/classes/installation.rb +27 -0
- data/lib/parse/model/classes/role.rb +20 -0
- data/lib/parse/model/classes/session.rb +26 -0
- data/lib/parse/model/classes/user.rb +185 -0
- data/lib/parse/model/core/actions.rb +40 -26
- data/lib/parse/model/core/properties.rb +126 -20
- data/lib/parse/model/core/querying.rb +63 -3
- data/lib/parse/model/core/schema.rb +9 -6
- data/lib/parse/model/date.rb +5 -1
- data/lib/parse/model/file.rb +12 -9
- data/lib/parse/model/geopoint.rb +6 -4
- data/lib/parse/model/model.rb +29 -21
- data/lib/parse/model/object.rb +29 -76
- data/lib/parse/model/pointer.rb +8 -6
- data/lib/parse/model/push.rb +4 -1
- data/lib/parse/query/constraint.rb +3 -0
- data/lib/parse/query/constraints.rb +6 -3
- data/lib/parse/query/operation.rb +3 -0
- data/lib/parse/query/ordering.rb +3 -0
- data/lib/parse/query.rb +85 -38
- data/lib/parse/stack/generators/rails.rb +3 -0
- data/lib/parse/stack/railtie.rb +2 -0
- data/lib/parse/stack/tasks.rb +4 -1
- data/lib/parse/stack/version.rb +4 -1
- data/lib/parse/stack.rb +3 -0
- data/lib/parse/webhooks/payload.rb +14 -8
- data/lib/parse/webhooks/registration.rb +11 -8
- data/lib/parse/webhooks.rb +11 -8
- data/lib/parse-stack.rb +3 -0
- data/parse-stack.gemspec +10 -8
- metadata +16 -4
@@ -0,0 +1,69 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative '../pointer'
|
5
|
+
require_relative 'collection_proxy'
|
6
|
+
require_relative 'pointer_collection_proxy'
|
7
|
+
require_relative 'relation_collection_proxy'
|
8
|
+
# a given Parse Pointer. The key of the property is implied to be the
|
9
|
+
# name of the class/parse table that contains the foreign associated record.
|
10
|
+
# All belongs to relationship column types have the special data type of :pointer.
|
11
|
+
module Parse
|
12
|
+
module Associations
|
13
|
+
|
14
|
+
module HasOne
|
15
|
+
|
16
|
+
def self.included(base)
|
17
|
+
base.extend(ClassMethods)
|
18
|
+
end
|
19
|
+
|
20
|
+
module ClassMethods
|
21
|
+
|
22
|
+
# has one are not property but instance scope methods
|
23
|
+
def has_one(key, scope = nil, **opts)
|
24
|
+
|
25
|
+
opts.reverse_merge!({as: key, field: parse_class.columnize, scope_only: false})
|
26
|
+
klassName = opts[:as].to_parse_class
|
27
|
+
foreign_field = opts[:field].to_sym
|
28
|
+
ivar = :"@_has_one_#{key}"
|
29
|
+
|
30
|
+
if self.method_defined?(key)
|
31
|
+
puts "Creating has_one :#{key} association. Will overwrite existing method #{self}##{key}."
|
32
|
+
end
|
33
|
+
|
34
|
+
define_method(key) do |*args, &block|
|
35
|
+
return nil if @id.nil?
|
36
|
+
query = Parse::Query.new(klassName, limit: 1)
|
37
|
+
query.where(foreign_field => self) unless opts[:scope_only] == true
|
38
|
+
|
39
|
+
if scope.is_a?(Proc)
|
40
|
+
# any method not part of Query, gets delegated to the instance object
|
41
|
+
instance = self
|
42
|
+
query.define_singleton_method(:method_missing) { |m, *args, &block| instance.send(m, *args, &block) }
|
43
|
+
query.define_singleton_method(:i) { instance }
|
44
|
+
|
45
|
+
if scope.arity.zero?
|
46
|
+
query.instance_exec(&scope)
|
47
|
+
query.conditions(*args) if args.present?
|
48
|
+
else
|
49
|
+
query.instance_exec(*args,&scope)
|
50
|
+
end
|
51
|
+
instance = nil # help clean up ruby gc
|
52
|
+
elsif args.present?
|
53
|
+
query.conditions(*args)
|
54
|
+
end
|
55
|
+
# query.define_singleton_method(:method_missing) do |m, *args, &block|
|
56
|
+
# self.first.send(m, *args, &block)
|
57
|
+
# end
|
58
|
+
return query.first if block.nil?
|
59
|
+
block.call(query.first)
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
@@ -1,3 +1,6 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
1
4
|
require 'active_model'
|
2
5
|
require 'active_support'
|
3
6
|
require 'active_support/inflector'
|
@@ -21,8 +24,8 @@ module Parse
|
|
21
24
|
# If they are not, and it is a hash, we check to see if it is a Parse hash.
|
22
25
|
def add(*items)
|
23
26
|
notify_will_change! if items.count > 0
|
24
|
-
items.flatten.
|
25
|
-
collection.push(item)
|
27
|
+
items.flatten.parse_objects.each do |item|
|
28
|
+
collection.push(item) if item.is_a?(Parse::Pointer)
|
26
29
|
end
|
27
30
|
@collection
|
28
31
|
end
|
@@ -30,20 +33,20 @@ module Parse
|
|
30
33
|
# removes items from the collection
|
31
34
|
def remove(*items)
|
32
35
|
notify_will_change! if items.count > 0
|
33
|
-
items.flatten.
|
36
|
+
items.flatten.parse_objects.each do |item|
|
34
37
|
collection.delete item
|
35
38
|
end
|
36
39
|
@collection
|
37
40
|
end
|
38
|
-
|
41
|
+
|
39
42
|
def add!(*items)
|
40
43
|
super(items.flatten.parse_pointers)
|
41
44
|
end
|
42
|
-
|
45
|
+
|
43
46
|
def add_unique!(*items)
|
44
47
|
super(items.flatten.parse_pointers)
|
45
48
|
end
|
46
|
-
|
49
|
+
|
47
50
|
def remove!(*items)
|
48
51
|
super(items.flatten.parse_pointers)
|
49
52
|
end
|
@@ -66,6 +69,10 @@ module Parse
|
|
66
69
|
collection.parse_pointers.as_json
|
67
70
|
end
|
68
71
|
|
72
|
+
def parse_pointers
|
73
|
+
collection.parse_pointers
|
74
|
+
end
|
75
|
+
|
69
76
|
end
|
70
77
|
|
71
78
|
end
|
@@ -1,3 +1,6 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
1
4
|
require 'active_support'
|
2
5
|
require 'active_support/inflector'
|
3
6
|
require 'active_support/core_ext/object'
|
@@ -66,7 +69,7 @@ module Parse
|
|
66
69
|
# is adding it to the @additions array and making sure it is
|
67
70
|
# removed from the @removals array.
|
68
71
|
def add(*items)
|
69
|
-
items = items.flatten.
|
72
|
+
items = items.flatten.parse_objects
|
70
73
|
return @collection if items.empty?
|
71
74
|
|
72
75
|
notify_will_change!
|
@@ -86,7 +89,7 @@ module Parse
|
|
86
89
|
# The process of removing is deleting it from the @removals array,
|
87
90
|
# and adding it to the @additions array.
|
88
91
|
def remove(*items)
|
89
|
-
items = items.flatten.
|
92
|
+
items = items.flatten.parse_objects
|
90
93
|
return @collection if items.empty?
|
91
94
|
notify_will_change!
|
92
95
|
additions_will_change!
|
data/lib/parse/model/bytes.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
1
4
|
require 'active_support'
|
2
5
|
require 'active_support/core_ext/object'
|
3
6
|
require_relative "model"
|
@@ -7,6 +10,7 @@ require 'base64'
|
|
7
10
|
module Parse
|
8
11
|
|
9
12
|
class Bytes < Model
|
13
|
+
ATTRIBUTES = {__type: :string, base64: :string }.freeze
|
10
14
|
attr_accessor :base64
|
11
15
|
def parse_class; TYPE_BYTES; end;
|
12
16
|
def parse_class; self.class.parse_class; end;
|
@@ -18,7 +22,7 @@ module Parse
|
|
18
22
|
end
|
19
23
|
|
20
24
|
def attributes
|
21
|
-
|
25
|
+
ATTRIBUTES
|
22
26
|
end
|
23
27
|
|
24
28
|
# takes a string and base64 encodes it
|
@@ -35,7 +39,7 @@ module Parse
|
|
35
39
|
if a.is_a?(String)
|
36
40
|
@bytes = a
|
37
41
|
elsif a.is_a?(Hash)
|
38
|
-
@bytes = a["base64"
|
42
|
+
@bytes = a["base64"] || @bytes
|
39
43
|
end
|
40
44
|
end
|
41
45
|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require_relative '../object'
|
4
|
+
|
5
|
+
module Parse
|
6
|
+
|
7
|
+
class Installation < Parse::Object
|
8
|
+
parse_class Parse::Model::CLASS_INSTALLATION
|
9
|
+
|
10
|
+
property :gcm_sender_id, :string, field: :GCMSenderId
|
11
|
+
property :app_identifier
|
12
|
+
property :app_name
|
13
|
+
property :app_version
|
14
|
+
property :badge, :integer
|
15
|
+
property :channels, :array
|
16
|
+
property :device_token
|
17
|
+
property :device_token_last_modified, :integer
|
18
|
+
property :device_type
|
19
|
+
property :installation_id
|
20
|
+
property :locale_identifier
|
21
|
+
property :parse_version
|
22
|
+
property :push_type
|
23
|
+
property :time_zone
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require_relative '../object'
|
4
|
+
require_relative 'user'
|
5
|
+
module Parse
|
6
|
+
|
7
|
+
class Role < Parse::Object
|
8
|
+
parse_class Parse::Model::CLASS_ROLE
|
9
|
+
property :name
|
10
|
+
|
11
|
+
has_many :roles, through: :relation
|
12
|
+
has_many :users, through: :relation
|
13
|
+
|
14
|
+
before_save do
|
15
|
+
acl.everyone true, false
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require_relative '../object'
|
4
|
+
|
5
|
+
module Parse
|
6
|
+
class Session < Parse::Object
|
7
|
+
parse_class Parse::Model::CLASS_SESSION
|
8
|
+
property :created_with, :object
|
9
|
+
property :expires_at, :date
|
10
|
+
property :installation_id
|
11
|
+
property :restricted, :boolean
|
12
|
+
property :session_token
|
13
|
+
|
14
|
+
belongs_to :user
|
15
|
+
|
16
|
+
def self.session(token)
|
17
|
+
response = client.fetch_session(token)
|
18
|
+
if response.success?
|
19
|
+
reutrn Parse::Session.build response.result
|
20
|
+
end
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# The User class provided by Parse with the required fields. You may
|
5
|
+
# add mixings to this class to add the app specific properties
|
6
|
+
require_relative '../object'
|
7
|
+
module Parse
|
8
|
+
|
9
|
+
class UsernameMissingError < StandardError; end; # 200
|
10
|
+
class PasswordMissingError < StandardError; end; # 201
|
11
|
+
class UsernameTakenError < StandardError; end; # 202
|
12
|
+
class EmailTakenError < StandardError; end; # 203
|
13
|
+
class EmailMissing < StandardError; end; # 204
|
14
|
+
|
15
|
+
class User < Parse::Object
|
16
|
+
|
17
|
+
parse_class Parse::Model::CLASS_USER
|
18
|
+
attr_accessor :session_token
|
19
|
+
property :auth_data, :object
|
20
|
+
property :email
|
21
|
+
property :password
|
22
|
+
property :username
|
23
|
+
|
24
|
+
before_save do
|
25
|
+
# You cannot specify user ACLs.
|
26
|
+
self.clear_attribute_change!(:acl)
|
27
|
+
end
|
28
|
+
|
29
|
+
def anonymous?
|
30
|
+
anonymous_id.nil?
|
31
|
+
end
|
32
|
+
|
33
|
+
def anonymous_id
|
34
|
+
auth_data['anonymous']['id'] if auth_data.present? && auth_data["anonymous"].is_a?(Hash)
|
35
|
+
end
|
36
|
+
|
37
|
+
def link_auth_data!(service_name, **data)
|
38
|
+
response = client.set_service_auth_data(id, service_name, data)
|
39
|
+
apply_attributes!(response.result) if response.success?
|
40
|
+
response.success?
|
41
|
+
end
|
42
|
+
|
43
|
+
def unlink_auth_data!(service_name)
|
44
|
+
response = client.set_service_auth_data(id, service_name, nil)
|
45
|
+
apply_attributes!(response.result) if response.success?
|
46
|
+
response.success?
|
47
|
+
end
|
48
|
+
|
49
|
+
# So that apply_attributes! works with session_token for login
|
50
|
+
def session_token_set_attribute!(token, track = false)
|
51
|
+
@session_token = token.to_s
|
52
|
+
end
|
53
|
+
alias_method :sessionToken_set_attribute!, :session_token_set_attribute!
|
54
|
+
|
55
|
+
def logged_in?
|
56
|
+
self.session_token.present?
|
57
|
+
end
|
58
|
+
|
59
|
+
def request_password_reset
|
60
|
+
return false if email.nil?
|
61
|
+
Parse::User.request_password_reset(email)
|
62
|
+
end
|
63
|
+
|
64
|
+
def signup!(passwd = nil)
|
65
|
+
self.password = passwd || password
|
66
|
+
if username.blank?
|
67
|
+
raise Parse::UsernameMissingError, "Signup requires an username."
|
68
|
+
end
|
69
|
+
|
70
|
+
if password.blank?
|
71
|
+
raise Parse::PasswordMissingError, "Signup requires a password."
|
72
|
+
end
|
73
|
+
|
74
|
+
signup_attrs = attribute_updates
|
75
|
+
signup_attrs.except! *Parse::Properties::BASE_FIELD_MAP.flatten
|
76
|
+
|
77
|
+
# first signup the user, then save any additional attributes
|
78
|
+
response = client.create_user signup_attrs
|
79
|
+
|
80
|
+
if response.success?
|
81
|
+
apply_attributes! response.result
|
82
|
+
return true
|
83
|
+
end
|
84
|
+
|
85
|
+
case response.code
|
86
|
+
when Parse::Response::ERROR_USERNAME_MISSING
|
87
|
+
raise Parse::UsernameMissingError, response
|
88
|
+
when Parse::Response::ERROR_PASSWORD_MISSING
|
89
|
+
raise Parse::PasswordMissingError, response
|
90
|
+
when Parse::Response::ERROR_USERNAME_TAKEN
|
91
|
+
raise Parse::UsernameTakenError, response
|
92
|
+
when Parse::Response::ERROR_EMAIL_TAKEN
|
93
|
+
raise Parse::EmailTakenError, response
|
94
|
+
end
|
95
|
+
raise response
|
96
|
+
end
|
97
|
+
|
98
|
+
def login!(passwd = nil)
|
99
|
+
self.password = passwd || self.password
|
100
|
+
response = client.login(username.to_s, password.to_s)
|
101
|
+
apply_attributes! response.result
|
102
|
+
self.session_token.present?
|
103
|
+
end
|
104
|
+
|
105
|
+
def logout
|
106
|
+
return true if self.session_token.blank?
|
107
|
+
client.logout session_token
|
108
|
+
self.session_token = nil
|
109
|
+
true
|
110
|
+
rescue => e
|
111
|
+
false
|
112
|
+
end
|
113
|
+
|
114
|
+
def session_token=(token)
|
115
|
+
@session = nil
|
116
|
+
@session_token = token
|
117
|
+
end
|
118
|
+
|
119
|
+
def session
|
120
|
+
if @session.blank? && @session_token.present?
|
121
|
+
response = client.fetch_session(@session_token)
|
122
|
+
@session ||= Parse::Session.new(response.result)
|
123
|
+
end
|
124
|
+
@session
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.create(body, **opts)
|
128
|
+
response = client.create_user(body, opts: opts)
|
129
|
+
if response.success?
|
130
|
+
return Parse::User.build response.result
|
131
|
+
end
|
132
|
+
|
133
|
+
case response.code
|
134
|
+
when Parse::Response::ERROR_USERNAME_MISSING
|
135
|
+
raise Parse::UsernameMissingError, response
|
136
|
+
when Parse::Response::ERROR_PASSWORD_MISSING
|
137
|
+
raise Parse::PasswordMissingError, response
|
138
|
+
when Parse::Response::ERROR_USERNAME_TAKEN
|
139
|
+
raise Parse::UsernameTakenError, response
|
140
|
+
when Parse::Response::ERROR_EMAIL_TAKEN
|
141
|
+
raise Parse::EmailTakenError, response
|
142
|
+
end
|
143
|
+
raise response
|
144
|
+
end
|
145
|
+
|
146
|
+
# method will signup or login a user given the third-party authentication data
|
147
|
+
def self.autologin_service(service_name, auth_data, body: {})
|
148
|
+
body = body.merge({authData: {service_name => auth_data} })
|
149
|
+
self.create(body)
|
150
|
+
end
|
151
|
+
|
152
|
+
def self.signup(username, password, email = nil, body: {})
|
153
|
+
body = body.merge({username: username, password: password })
|
154
|
+
body[:email] = email if email.present?
|
155
|
+
self.create(body)
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.login(username, password)
|
159
|
+
response = client.login(username.to_s, password.to_s)
|
160
|
+
response.success? ? Parse::User.build(response.result) : nil
|
161
|
+
end
|
162
|
+
|
163
|
+
def self.request_password_reset(email)
|
164
|
+
email = email.email if email.is_a?(Parse::User)
|
165
|
+
return false if email.blank?
|
166
|
+
response = client.reset_password(email)
|
167
|
+
response.success?
|
168
|
+
end
|
169
|
+
|
170
|
+
def self.session(token)
|
171
|
+
self.session! token
|
172
|
+
rescue InvalidSessionTokenError => e
|
173
|
+
nil
|
174
|
+
end
|
175
|
+
|
176
|
+
def self.session!(token)
|
177
|
+
# support Parse::Session objects
|
178
|
+
token = token.session_token if token.respond_to?(:session_token)
|
179
|
+
response = client.current_user(token)
|
180
|
+
response.success? ? Parse::User.build(response.result) : nil
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
@@ -1,3 +1,6 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
1
4
|
require 'active_model'
|
2
5
|
require 'active_support'
|
3
6
|
require 'active_support/inflector'
|
@@ -14,8 +17,8 @@ require_relative '../../client/request'
|
|
14
17
|
# hash request format Parse needs in order to modify relational information for classes.
|
15
18
|
module Parse
|
16
19
|
class RelationAction
|
17
|
-
ADD = "AddRelation"
|
18
|
-
REMOVE = "RemoveRelation"
|
20
|
+
ADD = "AddRelation"
|
21
|
+
REMOVE = "RemoveRelation"
|
19
22
|
attr_accessor :polarity, :key, :objects
|
20
23
|
# provide the column name of the field, polarity (true = add, false = remove) and the
|
21
24
|
# list of objects.
|
@@ -153,7 +156,7 @@ module Parse
|
|
153
156
|
op_hash = { field => op_hash }.as_json
|
154
157
|
end
|
155
158
|
|
156
|
-
response = client.update_object(parse_class, id, op_hash )
|
159
|
+
response = client.update_object(parse_class, id, op_hash, session_token: _session_token )
|
157
160
|
if response.error?
|
158
161
|
puts "[#{parse_class}:#{field} Operation] #{response.error}"
|
159
162
|
end
|
@@ -243,7 +246,7 @@ module Parse
|
|
243
246
|
warn "[#{parse_class}] warning: #{msg}"
|
244
247
|
end
|
245
248
|
end
|
246
|
-
response = client.update_object(parse_class, id, attribute_updates)
|
249
|
+
response = client.update_object(parse_class, id, attribute_updates, session_token: _session_token)
|
247
250
|
if response.success?
|
248
251
|
result = response.result
|
249
252
|
# Because beforeSave hooks can change the fields we are saving, any items that were
|
@@ -263,28 +266,38 @@ module Parse
|
|
263
266
|
|
264
267
|
# create this object in Parse
|
265
268
|
def create
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
269
|
+
run_callbacks :create do
|
270
|
+
res = client.create_object(parse_class, attribute_updates, session_token: _session_token)
|
271
|
+
unless res.error?
|
272
|
+
result = res.result
|
273
|
+
@id = result[Parse::Model::OBJECT_ID] || @id
|
274
|
+
@created_at = result["createdAt"] || @created_at
|
275
|
+
#if the object is created, updatedAt == createdAt
|
276
|
+
@updated_at = result["updatedAt"] || result["createdAt"] || @updated_at
|
277
|
+
# Because beforeSave hooks can change the fields we are saving, any items that were
|
278
|
+
# changed, are returned to us and we should apply those locally to be in sync.
|
279
|
+
set_attributes!(result)
|
280
|
+
end
|
281
|
+
puts "Error creating #{self.parse_class}: #{res.error}" if res.error?
|
282
|
+
res.success?
|
276
283
|
end
|
277
|
-
|
278
|
-
|
284
|
+
end
|
285
|
+
|
286
|
+
def _session_token
|
287
|
+
if @_session_token.respond_to?(:session_token)
|
288
|
+
@_session_token = @_session_token.session_token
|
289
|
+
end
|
290
|
+
@_session_token
|
279
291
|
end
|
280
292
|
|
281
293
|
# saves the object. If the object has not changed, it is a noop. If it is new,
|
282
294
|
# we will create the object. If the object has an id, we will update the record.
|
283
295
|
# You can define before and after :save callbacks
|
284
296
|
# autoraise: set to true will automatically raise an exception if the save fails
|
285
|
-
def save(autoraise: false)
|
297
|
+
def save(autoraise: false, session: nil)
|
286
298
|
return true unless changed?
|
287
299
|
success = false
|
300
|
+
@_session_token = session
|
288
301
|
run_callbacks :save do
|
289
302
|
#first process the create/update action if any
|
290
303
|
#then perform any relation changes that need to be performed
|
@@ -311,21 +324,23 @@ module Parse
|
|
311
324
|
end
|
312
325
|
|
313
326
|
end #callbacks
|
327
|
+
@_session_token = nil
|
314
328
|
success
|
315
329
|
end
|
316
330
|
|
317
331
|
# shortcut for raising an exception of saving this object failed.
|
318
|
-
def save!
|
319
|
-
save(autoraise: true)
|
332
|
+
def save!(session: nil)
|
333
|
+
save(autoraise: true, session: session)
|
320
334
|
end
|
321
335
|
|
322
336
|
# only destroy the object if it has an id. You can setup before and after
|
323
337
|
#callback hooks on :destroy
|
324
|
-
def destroy
|
338
|
+
def destroy(session: nil)
|
325
339
|
return false if new?
|
340
|
+
@_session_token = session
|
326
341
|
success = false
|
327
342
|
run_callbacks :destroy do
|
328
|
-
res = client.delete_object parse_class, id
|
343
|
+
res = client.delete_object parse_class, id, session_token: _session_token
|
329
344
|
success = res.success?
|
330
345
|
if success
|
331
346
|
@id = nil
|
@@ -335,6 +350,7 @@ module Parse
|
|
335
350
|
end
|
336
351
|
# Your create action methods here
|
337
352
|
end
|
353
|
+
@_session_token = nil
|
338
354
|
success
|
339
355
|
end
|
340
356
|
|
@@ -386,16 +402,14 @@ module Parse
|
|
386
402
|
raise "Unable to update relations for a new object." if new?
|
387
403
|
# get all the relational changes (both additions and removals)
|
388
404
|
additions, removals = relation_change_operations
|
389
|
-
|
390
|
-
# addition_response = client.update_object(parse_class, id, additions)
|
405
|
+
|
391
406
|
responses = []
|
392
407
|
# Send parallel Parse requests for each of the items to update.
|
393
408
|
# since we will have multiple responses, we will track it in array
|
394
409
|
[removals, additions].threaded_each do |ops|
|
395
410
|
next if ops.empty? #if no operations to be performed, then we are done
|
396
|
-
responses << client.update_object(parse_class, @id, ops)
|
411
|
+
responses << client.update_object(parse_class, @id, ops, session_token: _session_token)
|
397
412
|
end
|
398
|
-
#response = client.update_object(parse_class, id, relation_updates)
|
399
413
|
# check if any of them ended up in error
|
400
414
|
has_error = responses.any? { |response| response.error? }
|
401
415
|
# if everything was ok, find the last response to be returned and update
|
@@ -410,7 +424,7 @@ module Parse
|
|
410
424
|
def set_attributes!(hash, dirty_track = false)
|
411
425
|
return unless hash.is_a?(Hash)
|
412
426
|
hash.each do |k,v|
|
413
|
-
next if k ==
|
427
|
+
next if k == Parse::Model::OBJECT_ID || k == Parse::Model::ID
|
414
428
|
method = "#{k}_set_attribute!"
|
415
429
|
send(method, v, dirty_track) if respond_to?(method)
|
416
430
|
end
|