parse-stack 1.5.3 → 1.6.0

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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.github/parse-ruby-sdk.png +0 -0
  3. data/Changes.md +25 -1
  4. data/Gemfile.lock +4 -4
  5. data/README.md +37 -31
  6. data/bin/console +3 -0
  7. data/lib/parse/api/all.rb +2 -1
  8. data/lib/parse/api/apps.rb +12 -0
  9. data/lib/parse/api/config.rb +5 -1
  10. data/lib/parse/api/files.rb +1 -0
  11. data/lib/parse/api/hooks.rb +1 -0
  12. data/lib/parse/api/objects.rb +4 -1
  13. data/lib/parse/api/push.rb +1 -0
  14. data/lib/parse/api/{schemas.rb → schema.rb} +7 -0
  15. data/lib/parse/api/server.rb +44 -0
  16. data/lib/parse/api/sessions.rb +1 -0
  17. data/lib/parse/api/users.rb +4 -1
  18. data/lib/parse/client.rb +109 -73
  19. data/lib/parse/client/authentication.rb +2 -1
  20. data/lib/parse/client/batch.rb +9 -1
  21. data/lib/parse/client/body_builder.rb +16 -1
  22. data/lib/parse/client/caching.rb +15 -13
  23. data/lib/parse/client/protocol.rb +27 -15
  24. data/lib/parse/client/response.rb +26 -8
  25. data/lib/parse/model/acl.rb +1 -1
  26. data/lib/parse/model/associations/belongs_to.rb +18 -19
  27. data/lib/parse/model/associations/collection_proxy.rb +6 -0
  28. data/lib/parse/model/associations/has_many.rb +5 -6
  29. data/lib/parse/model/bytes.rb +4 -1
  30. data/lib/parse/model/classes/user.rb +46 -44
  31. data/lib/parse/model/core/actions.rb +508 -460
  32. data/lib/parse/model/core/builder.rb +75 -0
  33. data/lib/parse/model/core/errors.rb +9 -0
  34. data/lib/parse/model/core/fetching.rb +42 -38
  35. data/lib/parse/model/core/properties.rb +46 -27
  36. data/lib/parse/model/core/querying.rb +231 -228
  37. data/lib/parse/model/core/schema.rb +76 -74
  38. data/lib/parse/model/date.rb +10 -2
  39. data/lib/parse/model/file.rb +16 -2
  40. data/lib/parse/model/geopoint.rb +9 -2
  41. data/lib/parse/model/model.rb +38 -7
  42. data/lib/parse/model/object.rb +60 -19
  43. data/lib/parse/model/pointer.rb +22 -1
  44. data/lib/parse/model/push.rb +6 -2
  45. data/lib/parse/query.rb +57 -11
  46. data/lib/parse/query/constraint.rb +5 -2
  47. data/lib/parse/query/constraints.rb +588 -589
  48. data/lib/parse/query/ordering.rb +2 -2
  49. data/lib/parse/stack.rb +1 -0
  50. data/lib/parse/stack/version.rb +1 -1
  51. data/lib/parse/webhooks.rb +30 -29
  52. data/lib/parse/webhooks/payload.rb +181 -168
  53. data/lib/parse/webhooks/registration.rb +1 -1
  54. data/parse-stack.gemspec +9 -9
  55. metadata +9 -12
@@ -5,18 +5,30 @@
5
5
  module Parse
6
6
  # Set of Parse protocol constants.
7
7
  module Protocol
8
- HOST = 'api.parse.com'
9
- SERVER_URL = 'https://api.parse.com/1/'
10
- APP_ID = 'X-Parse-Application-Id'
11
- API_KEY = 'X-Parse-REST-API-Key'
12
- MASTER_KEY = 'X-Parse-Master-Key'
13
- SESSION_TOKEN = 'X-Parse-Session-Token'
14
- REVOCABLE_SESSION = 'X-Parse-Revocable-Session'
15
- EMAIL = 'X-Parse-Email'
16
- PASSWORD = 'X-Parse-Password'
17
- INSTALLATION_ID = 'Parse-Installation-Id'
18
- CONTENT_TYPE = 'Content-Type'
19
- CONTENT_TYPE_FORMAT = 'application/json; charset=utf-8'
8
+ # The default server url, based on the hosted Parse platform.
9
+ SERVER_URL = 'https://api.parse.com/1/'.freeze
10
+ # The default legacy server url, based on the hosted Parse platform.
11
+ LEGACY_SERVER_URL = 'https://api.parse.com/1/'.freeze
12
+ # The request header field to send the application Id.
13
+ APP_ID = 'X-Parse-Application-Id'
14
+ # The request header field to send the REST API key.
15
+ API_KEY = 'X-Parse-REST-API-Key'
16
+ # The request header field to send the Master key.
17
+ MASTER_KEY = 'X-Parse-Master-Key'
18
+ # The request header field to send the revocable Session key.
19
+ SESSION_TOKEN = 'X-Parse-Session-Token'
20
+ # The request header field to request a revocable session token.
21
+ REVOCABLE_SESSION = 'X-Parse-Revocable-Session'
22
+ # The request header field to send the installation id.
23
+ INSTALLATION_ID = 'Parse-Installation-Id'
24
+ # The request header field to send an email when authenticating with Parse hosted platform.
25
+ EMAIL = 'X-Parse-Email'
26
+ # The request header field to send the password when authenticating with the Parse hosted platform.
27
+ PASSWORD = 'X-Parse-Password'
28
+ # The request header field for the Content type.
29
+ CONTENT_TYPE = 'Content-Type'
30
+ # The default content type format for sending API requests.
31
+ CONTENT_TYPE_FORMAT = 'application/json; charset=utf-8'
20
32
  end
21
33
 
22
34
  # All Parse error codes.
@@ -67,8 +79,8 @@ module Parse
67
79
  # LinkedIdMissing 250 Error code indicating that a user cannot be linked to an account because that account's id could not be found.
68
80
  # InvalidLinkedSession 251 Error code indicating that a user with a linked (e.g. Facebook) account has an invalid session.
69
81
  # UnsupportedService 252 Error code indicating that a service being linked (e.g. Facebook or Twitter) is unsupported.
70
- module ErrorCodes
71
-
72
- end
82
+ # module ErrorCodes
83
+ #
84
+ # end
73
85
 
74
86
  end
@@ -3,30 +3,47 @@
3
3
 
4
4
  require 'active_support'
5
5
  require 'active_support/json'
6
- # This is the model that represents a response from Parse. A Response can also
7
- # be a set of responses (from a Batch response).
6
+
8
7
  module Parse
9
8
 
10
- class ResponseError < StandardError; end;
9
+ # Represents a response from Parse server. A response can also
10
+ # be a set of responses (from a Batch response).
11
11
  class Response
12
12
  include Enumerable
13
13
 
14
+ # Code for an unknown error.
14
15
  ERROR_INTERNAL = 1
16
+ # Code when the server returns a 500 or is non-responsive.
15
17
  ERROR_SERVICE_UNAVAILABLE = 2
18
+ # Code when the request times out.
16
19
  ERROR_TIMEOUT = 124
20
+ # Code when the requests per second limit as been exceeded.
17
21
  ERROR_EXCEEDED_BURST_LIMIT = 155
22
+ # Code when a requested record is not found.
18
23
  ERROR_OBJECT_NOT_FOUND = 101
24
+ # Code when the username is missing in request.
19
25
  ERROR_USERNAME_MISSING = 200
26
+ # Code when the password is missing in request.
20
27
  ERROR_PASSWORD_MISSING = 201
28
+ # Code when the username is already in the system.
21
29
  ERROR_USERNAME_TAKEN = 202
30
+ # Code when the email is already in the system.
22
31
  ERROR_EMAIL_TAKEN = 203
32
+ # Code when the email is not found
23
33
  ERROR_EMAIL_NOT_FOUND = 205
34
+ # Code when the email is invalid
24
35
  ERROR_EMAIL_INVALID = 125
25
36
 
26
- ERROR = "error"
27
- CODE = "code"
28
- RESULTS = "results"
29
- COUNT = "count"
37
+ # The field name for the error.
38
+ ERROR = "error".freeze
39
+ # The field name for the success.
40
+ SUCCESS = "success".freeze
41
+ # The field name for the error code.
42
+ CODE = "code".freeze
43
+ # The field name for the results of the request.
44
+ RESULTS = "results".freeze
45
+ # The field name for the count result in a count response.
46
+ COUNT = "count".freeze
30
47
 
31
48
  # @!attribute [rw] parse_class
32
49
  # @return [String] the Parse class for this request
@@ -85,7 +102,7 @@ module Parse
85
102
  # if batch response, generate array based on the response hash.
86
103
  @result.map do |r|
87
104
  next r unless r.is_a?(Hash)
88
- hash = r["success"] || r[ERROR]
105
+ hash = r[SUCCESS] || r[ERROR]
89
106
  Parse::Response.new hash
90
107
  end
91
108
  end
@@ -145,6 +162,7 @@ module Parse
145
162
  self
146
163
  end
147
164
 
165
+ # @!visibility private
148
166
  def inspect
149
167
  if error?
150
168
  "#<#{self.class} @code=#{code} @error='#{error}'>"
@@ -100,7 +100,7 @@ module Parse
100
100
  def permissions
101
101
  @permissions ||= {}
102
102
  end
103
-
103
+ # The key field value for public permissions.
104
104
  PUBLIC = "*"
105
105
 
106
106
  # Create a new ACL with default Public read/write permissions and any
@@ -57,23 +57,6 @@ module Parse
57
57
  # A hash mapping of all belongs_to associations for this model.
58
58
  # @return [Hash]
59
59
 
60
- # @!method key?
61
- # A dynamically generated method based on the value of `key` passed to the
62
- # belongs_to method, which returns true if this instance has a pointer for
63
- # this field.
64
- # @example
65
- #
66
- # class Post < Parse::Object
67
- # belongs_to :author # generates 'author?'
68
- # end
69
- #
70
- # post = Post.new
71
- # post.author? # => false
72
- # post.author = Author.new
73
- # post.author? # => true
74
- # @return [Boolean] true if field contains a Parse::Pointer or subclass.
75
-
76
-
77
60
  # @!method self.belongs_to(key, opts = {})
78
61
  # Creates a one-to-one association with another Parse model.
79
62
  # @param [Symbol] key The singularized version of the foreign class and the name of the
@@ -106,6 +89,22 @@ module Parse
106
89
  # @return [Parse::Object] a Parse::Object subclass when using the accessor
107
90
  # when fetching the association.
108
91
 
92
+ # @!method key?
93
+ # A dynamically generated method based on the value of `key` passed to the
94
+ # belongs_to method, which returns true if this instance has a pointer for
95
+ # this field.
96
+ # @example
97
+ #
98
+ # class Post < Parse::Object
99
+ # belongs_to :author # generates 'author?'
100
+ # end
101
+ #
102
+ # post = Post.new
103
+ # post.author? # => false
104
+ # post.author = Author.new
105
+ # post.author? # => true
106
+ # @return [Boolean] true if field contains a Parse::Pointer or subclass.
107
+
109
108
  # @!visibility private
110
109
  def self.included(base)
111
110
  base.extend(ClassMethods)
@@ -130,10 +129,10 @@ module Parse
130
129
  set_attribute_method = :"#{key}_set_attribute!"
131
130
 
132
131
  if self.fields[key].present? && Parse::Properties::BASE_FIELD_MAP[key].nil?
133
- raise Parse::Properties::DefinitionError, "Belongs relation #{self}##{key} already defined with type #{klassName}"
132
+ raise ArgumentError, "Belongs relation #{self}##{key} already defined with type #{klassName}"
134
133
  end
135
134
  if self.fields[parse_field].present?
136
- raise Parse::Properties::DefinitionError, "Alias belongs_to #{self}##{parse_field} conflicts with previously defined property."
135
+ raise ArgumentError, "Alias belongs_to #{self}##{parse_field} conflicts with previously defined property."
137
136
  end
138
137
  # store this attribute in the attributes hash with the proper remote column name.
139
138
  # we know the type is pointer.
@@ -113,6 +113,7 @@ module Parse
113
113
  # @!attribute [rw] collection
114
114
  # Set the internal collection of items without dirty tracking or
115
115
  # change notifications.
116
+ # @return [Array] the collection
116
117
  def set_collection!(list)
117
118
  @collection = list
118
119
  end
@@ -230,6 +231,7 @@ module Parse
230
231
  collection.count
231
232
  end
232
233
 
234
+ # @return [Hash] a JSON representation
233
235
  def as_json(*args)
234
236
  collection.as_json(args)
235
237
  end
@@ -253,21 +255,25 @@ module Parse
253
255
  forward "#{@key}_will_change!"
254
256
  end
255
257
 
258
+ # Alias for Array#each
256
259
  def each
257
260
  return collection.enum_for(:each) unless block_given?
258
261
  collection.each &Proc.new
259
262
  end
260
263
 
264
+ # Alias for Array#map
261
265
  def map
262
266
  return collection.enum_for(:map) unless block_given?
263
267
  collection.map &Proc.new
264
268
  end
265
269
 
270
+ # Alias for Array#select
266
271
  def select
267
272
  return collection.enum_for(:select) unless block_given?
268
273
  collection.select &Proc.new
269
274
  end
270
275
 
276
+ # @!visibility private
271
277
  def inspect
272
278
  "#<#{self.class} changed?=#{changed?} @collection=#{@collection.inspect} >"
273
279
  end
@@ -366,15 +366,15 @@ module Parse
366
366
  results.send(m, *args, &chained_block)
367
367
  end
368
368
 
369
- query.define_singleton_method(:to_s) { self.results.to_s }
370
- query.define_singleton_method(:inspect) { self.results.to_a.inspect }
371
-
369
+ Parse::Query.apply_auto_introspection!(query)
370
+
372
371
  return query if block.nil?
373
372
  query.results(&block)
374
373
  end
375
374
 
376
375
  end
377
376
 
377
+ # Define a one-to-many or many-to-many association between the local model and a foreign class.
378
378
  def has_many(key, scope = nil, **opts)
379
379
  opts[:through] ||= :query
380
380
 
@@ -398,10 +398,10 @@ module Parse
398
398
 
399
399
  # verify that the user did not duplicate properties or defined different properties with the same name
400
400
  if self.fields[key].present? && Parse::Properties::BASE_FIELD_MAP[key].nil?
401
- raise Parse::Properties::DefinitionError, "Has_many property #{self}##{key} already defined with type #{klassName}"
401
+ raise ArgumentError, "Has_many property #{self}##{key} already defined with type #{klassName}"
402
402
  end
403
403
  if self.fields[parse_field].present?
404
- raise Parse::Properties::DefinitionError, "Alias has_many #{self}##{parse_field} conflicts with previously defined property."
404
+ raise ArgumentError, "Alias has_many #{self}##{parse_field} conflicts with previously defined property."
405
405
  end
406
406
  # validations
407
407
  validates_presence_of(key) if opts[:required]
@@ -545,7 +545,6 @@ module Parse
545
545
  end
546
546
 
547
547
  # @return [Boolean] true if there are pending relational changes for
548
- # associations defined using Parse Relations.
549
548
  def relation_changes?
550
549
  changed.any? { |key| relations[key.to_sym] }
551
550
  end
@@ -11,6 +11,7 @@ module Parse
11
11
 
12
12
  # Support for the Bytes type in Parse
13
13
  class Bytes < Model
14
+ # The default attributes in a Parse Bytes hash.
14
15
  ATTRIBUTES = {__type: :string, base64: :string }.freeze
15
16
  # @return [String] the base64 string representing the content
16
17
  attr_accessor :base64
@@ -26,7 +27,9 @@ module Parse
26
27
  @base64 = (bytes.is_a?(Bytes) ? bytes.base64 : bytes).dup
27
28
  end
28
29
 
29
- # @return [Hash]
30
+ # @!attribute attributes
31
+ # Supports for mass assignment of values and encoding to JSON.
32
+ # @return [ATTRIBUTES]
30
33
  def attributes
31
34
  ATTRIBUTES
32
35
  end
@@ -3,20 +3,22 @@
3
3
 
4
4
  require_relative '../object'
5
5
  module Parse
6
- # 200 Error code indicating that the username is missing or empty.
7
- class UsernameMissingError < StandardError; end;
8
- # 201 Error code indicating that the password is missing or empty.
9
- class PasswordMissingError < StandardError; end;
10
- # Error code 202: indicating that the username has already been taken.
11
- class UsernameTakenError < StandardError; end;
12
- # 203 Error code indicating that the email has already been taken.
13
- class EmailTakenError < StandardError; end;
14
- # 204 Error code indicating that the email is missing, but must be specified.
15
- class EmailMissing < StandardError; end;
16
- # 205 Error code indicating that a user with the specified email was not found.
17
- class EmailNotFound < StandardError; end;
18
- # 125 Error code indicating that the email address was invalid.
19
- class InvalidEmailAddress < StandardError; end;
6
+ class Error
7
+ # 200 Error code indicating that the username is missing or empty.
8
+ class UsernameMissingError < Error; end;
9
+ # 201 Error code indicating that the password is missing or empty.
10
+ class PasswordMissingError < Error; end;
11
+ # Error code 202: indicating that the username has already been taken.
12
+ class UsernameTakenError < Error; end;
13
+ # 203 Error code indicating that the email has already been taken.
14
+ class EmailTakenError < Error; end;
15
+ # 204 Error code indicating that the email is missing, but must be specified.
16
+ class EmailMissing < Error; end;
17
+ # 205 Error code indicating that a user with the specified email was not found.
18
+ class EmailNotFound < Error; end;
19
+ # 125 Error code indicating that the email address was invalid.
20
+ class InvalidEmailAddress < Error; end;
21
+ end
20
22
 
21
23
  # The main class representing the _User table in Parse. A user can either be signed up or anonymous.
22
24
  # All users need to have a username and a password, with email being optional but globally unique if set.
@@ -168,20 +170,20 @@ module Parse
168
170
  # Adds the third-party authentication data to for a given service.
169
171
  # @param service_name [Symbol] The name of the service (ex. :facebook)
170
172
  # @param data [Hash] The body of the OAuth data. Dependent on each service.
171
- # @raise [ResponseError] If user was not successfully linked
173
+ # @raise [Parse::Client::ResponseError] If user was not successfully linked
172
174
  def link_auth_data!(service_name, **data)
173
175
  response = client.set_service_auth_data(id, service_name, data)
174
- raise Parse::ResponseError, response if response.error?
176
+ raise Parse::Client::ResponseError, response if response.error?
175
177
  apply_attributes!(response.result)
176
178
  end
177
179
 
178
180
  # Removes third-party authentication data for this user
179
181
  # @param service_name [Symbol] The name of the third-party service (ex. :facebook)
180
- # @raise [ResponseError] If user was not successfully unlinked
182
+ # @raise [Parse::Client::ResponseError] If user was not successfully unlinked
181
183
  # @return [Boolean] True/false if successful.
182
184
  def unlink_auth_data!(service_name)
183
185
  response = client.set_service_auth_data(id, service_name, nil)
184
- raise Parse::ResponseError, response if response.error?
186
+ raise Parse::Client::ResponseError, response if response.error?
185
187
  apply_attributes!(response.result)
186
188
  end
187
189
 
@@ -208,21 +210,21 @@ module Parse
208
210
 
209
211
  # You may set a password for this user when you are creating them. Parse never returns a
210
212
  # @param passwd The user's password to be used for signing up.
211
- # @raise [Parse::UsernameMissingError] If username is missing.
212
- # @raise [Parse::PasswordMissingError] If password is missing.
213
- # @raise [Parse::UsernameTakenError] If the username has already been taken.
214
- # @raise [Parse::EmailTakenError] If the email has already been taken (or exists in the system).
215
- # @raise [Parse::InvalidEmailAddress] If the email is invalid.
216
- # @raise [Parse::ResponseError] An unknown error occurred.
213
+ # @raise [Parse::Error::UsernameMissingError] If username is missing.
214
+ # @raise [Parse::Error::PasswordMissingError] If password is missing.
215
+ # @raise [Parse::Error::UsernameTakenError] If the username has already been taken.
216
+ # @raise [Parse::Error::EmailTakenError] If the email has already been taken (or exists in the system).
217
+ # @raise [Parse::Error::InvalidEmailAddress] If the email is invalid.
218
+ # @raise [Parse::Client::ResponseError] An unknown error occurred.
217
219
  # @return [Boolean] True if signup it was successful. If it fails an exception is thrown.
218
220
  def signup!(passwd = nil)
219
221
  self.password = passwd || password
220
222
  if username.blank?
221
- raise Parse::UsernameMissingError, "Signup requires a username."
223
+ raise Parse::Error::UsernameMissingError, "Signup requires a username."
222
224
  end
223
225
 
224
226
  if password.blank?
225
- raise Parse::PasswordMissingError, "Signup requires a password."
227
+ raise Parse::Error::PasswordMissingError, "Signup requires a password."
226
228
  end
227
229
 
228
230
  signup_attrs = attribute_updates
@@ -238,17 +240,17 @@ module Parse
238
240
 
239
241
  case response.code
240
242
  when Parse::Response::ERROR_USERNAME_MISSING
241
- raise Parse::UsernameMissingError, response
243
+ raise Parse::Error::UsernameMissingError, response
242
244
  when Parse::Response::ERROR_PASSWORD_MISSING
243
- raise Parse::PasswordMissingError, response
245
+ raise Parse::Error::PasswordMissingError, response
244
246
  when Parse::Response::ERROR_USERNAME_TAKEN
245
- raise Parse::UsernameTakenError, response
247
+ raise Parse::Error::UsernameTakenError, response
246
248
  when Parse::Response::ERROR_EMAIL_TAKEN
247
- raise Parse::EmailTakenError, response
249
+ raise Parse::Error::EmailTakenError, response
248
250
  when Parse::Response::ERROR_EMAIL_INVALID
249
- raise Parse::InvalidEmailAddress, response
251
+ raise Parse::Error::InvalidEmailAddress, response
250
252
  end
251
- raise Parse::ResponseError, response
253
+ raise Parse::Client::ResponseError, response
252
254
  end
253
255
 
254
256
  # Login and get a session token for this user.
@@ -290,12 +292,12 @@ module Parse
290
292
  # Creates a new Parse::User given a hash that maps to the fields defined in your Parse::User collection.
291
293
  # @param body [Hash] The hash containing the Parse::User fields. The field `username` and `password` are required.
292
294
  # @option opts [Boolean] :master_key Whether the master key should be used for this request.
293
- # @raise [UsernameMissingError] If username is missing.
294
- # @raise [PasswordMissingError] If password is missing.
295
- # @raise [UsernameTakenError] If the username has already been taken.
296
- # @raise [EmailTakenError] If the email has already been taken (or exists in the system).
297
- # @raise [InvalidEmailAddress] If the email is invalid.
298
- # @raise [ResponseError] An unknown error occurred.
295
+ # @raise [Parse::Error::UsernameMissingError] If username is missing.
296
+ # @raise [Parse::Error::PasswordMissingError] If password is missing.
297
+ # @raise [Parse::Error::UsernameTakenError] If the username has already been taken.
298
+ # @raise [Parse::Error::EmailTakenError] If the email has already been taken (or exists in the system).
299
+ # @raise [Parse::Error::InvalidEmailAddress] If the email is invalid.
300
+ # @raise [Parse::Client::ResponseError] An unknown error occurred.
299
301
  # @return [User] Returns a successfully created Parse::User.
300
302
  def self.create(body, **opts)
301
303
  response = client.create_user(body, opts: opts)
@@ -305,15 +307,15 @@ module Parse
305
307
 
306
308
  case response.code
307
309
  when Parse::Response::ERROR_USERNAME_MISSING
308
- raise Parse::UsernameMissingError, response
310
+ raise Parse::Error::UsernameMissingError, response
309
311
  when Parse::Response::ERROR_PASSWORD_MISSING
310
- raise Parse::PasswordMissingError, response
312
+ raise Parse::Error::PasswordMissingError, response
311
313
  when Parse::Response::ERROR_USERNAME_TAKEN
312
- raise Parse::UsernameTakenError, response
314
+ raise Parse::Error::UsernameTakenError, response
313
315
  when Parse::Response::ERROR_EMAIL_TAKEN
314
- raise Parse::EmailTakenError, response
316
+ raise Parse::Error::EmailTakenError, response
315
317
  end
316
- raise Parse::ResponseError, response
318
+ raise Parse::Client::ResponseError, response
317
319
  end
318
320
 
319
321
  # Automatically and implicitly signup a user if it did not already exists and
@@ -372,7 +374,7 @@ module Parse
372
374
  # @see #session!
373
375
  def self.session(token, opts = {})
374
376
  self.session! token, opts
375
- rescue InvalidSessionTokenError => e
377
+ rescue Parse::Error::InvalidSessionTokenError => e
376
378
  nil
377
379
  end
378
380