parse-stack 1.5.2 → 1.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +5 -0
  3. data/Gemfile.lock +1 -1
  4. data/README.md +40 -80
  5. data/lib/parse/api/all.rb +7 -0
  6. data/lib/parse/api/analytics.rb +8 -3
  7. data/lib/parse/api/apps.rb +29 -1
  8. data/lib/parse/api/batch.rb +14 -129
  9. data/lib/parse/api/cloud_functions.rb +9 -0
  10. data/lib/parse/api/config.rb +10 -1
  11. data/lib/parse/api/files.rb +7 -2
  12. data/lib/parse/api/hooks.rb +45 -2
  13. data/lib/parse/api/objects.rb +43 -6
  14. data/lib/parse/api/push.rb +6 -1
  15. data/lib/parse/api/schemas.rb +15 -1
  16. data/lib/parse/api/sessions.rb +5 -0
  17. data/lib/parse/api/users.rb +64 -5
  18. data/lib/parse/client/authentication.rb +25 -8
  19. data/lib/parse/client/batch.rb +206 -0
  20. data/lib/parse/client/body_builder.rb +12 -6
  21. data/lib/parse/client/caching.rb +42 -10
  22. data/lib/parse/client/protocol.rb +51 -46
  23. data/lib/parse/client/response.rb +1 -47
  24. data/lib/parse/client.rb +171 -42
  25. data/lib/parse/model/acl.rb +184 -39
  26. data/lib/parse/model/associations/belongs_to.rb +1 -0
  27. data/lib/parse/model/classes/role.rb +7 -1
  28. data/lib/parse/model/classes/session.rb +7 -3
  29. data/lib/parse/model/classes/user.rb +107 -0
  30. data/lib/parse/model/core/actions.rb +166 -115
  31. data/lib/parse/model/core/fetching.rb +105 -0
  32. data/lib/parse/model/core/properties.rb +40 -13
  33. data/lib/parse/model/core/querying.rb +123 -39
  34. data/lib/parse/model/core/schema.rb +22 -32
  35. data/lib/parse/model/object.rb +26 -20
  36. data/lib/parse/model/pointer.rb +1 -0
  37. data/lib/parse/query/constraint.rb +65 -27
  38. data/lib/parse/query/constraints.rb +0 -3
  39. data/lib/parse/query/operation.rb +33 -22
  40. data/lib/parse/query/ordering.rb +10 -5
  41. data/lib/parse/stack/generators/rails.rb +5 -1
  42. data/lib/parse/stack/generators/templates/model_installation.rb +1 -1
  43. data/lib/parse/stack/generators/templates/model_role.rb +1 -1
  44. data/lib/parse/stack/generators/templates/model_session.rb +2 -2
  45. data/lib/parse/stack/generators/templates/model_user.rb +1 -1
  46. data/lib/parse/stack/generators/templates/parse.rb +0 -1
  47. data/lib/parse/stack/railtie.rb +1 -0
  48. data/lib/parse/stack/tasks.rb +3 -1
  49. data/lib/parse/stack/version.rb +3 -1
  50. data/lib/parse/webhooks/registration.rb +3 -3
  51. data/lib/parse/webhooks.rb +88 -7
  52. metadata +5 -3
data/lib/parse/client.rb CHANGED
@@ -11,6 +11,7 @@ require 'active_support/core_ext/time/calculations'
11
11
  require 'active_support/core_ext'
12
12
  require_relative "client/request"
13
13
  require_relative "client/response"
14
+ require_relative "client/batch"
14
15
  require_relative "client/body_builder"
15
16
  require_relative "client/authentication"
16
17
  require_relative "client/caching"
@@ -30,6 +31,9 @@ module Parse
30
31
  # Retrieve the App specific Parse configuration parameters. The configuration
31
32
  # for a connection is cached after the first request. Use the bang version to
32
33
  # force update from the Parse backend.
34
+ # @example
35
+ # val = Parse.config["myKey"]
36
+ # val = Parse.config["myKey"] # cached
33
37
  # @see Parse.config!
34
38
  # @param conn [Symbol] the name of the client connection to use.
35
39
  # @return [Hash] the Parse config hash for the session.
@@ -38,6 +42,9 @@ module Parse
38
42
  end
39
43
 
40
44
  # Set a parameter in the Parse configuration for an application.
45
+ # @example
46
+ # # update a config with Parse
47
+ # Parse.set_config "myKey", "someValue"
41
48
  # @param field [String] the name configuration variable.
42
49
  # @param value [Object] the value configuration variable. Only Parse types are supported.
43
50
  # @param conn [Symbol] the name of the client connection to use.
@@ -47,6 +54,9 @@ module Parse
47
54
  end
48
55
 
49
56
  # Set a key value pairs in the Parse configuration for an application.
57
+ # @example
58
+ # # batch update several
59
+ # Parse.update_config({fieldEnabled: true, searchMiles: 50})
50
60
  # @param params [Hash] a set of key value pairs to set in the Parse configuration.
51
61
  # @param conn [Symbol] the name of the client connection to use.
52
62
  # @return [Hash] the Parse config hash for the session.
@@ -134,31 +144,68 @@ module Parse
134
144
  @clients[conn] ||= self.new
135
145
  end
136
146
 
137
- # Setup the Parse-Stack framework with the appropriate Parse app keys and middleware.
138
- # @yield a block for additional configuration
139
- # @param opts [Hash] the set of options to configure the :default Parse::Client connection.
140
- # @return [Parse::Client]
141
- # @see Parse::Client#initialize
147
+ # Setup the a new client with the appropriate Parse app keys, middleware and
148
+ # options.
149
+ # @example
150
+ # Parse.setup app_id: "YOUR_APP_ID",
151
+ # api_key: "YOUR_API_KEY",
152
+ # master_key: "YOUR_MASTER_KEY", # optional
153
+ # server_url: 'https://api.parse.com/1/' #default
154
+ # @param opts (see Parse::Client#initialize)
155
+ # @option opts (see Parse::Client#initialize)
156
+ # @yield the block for additional configuration with Faraday middleware.
157
+ # @return (see Parse::Client#initialize)
158
+ # @see Parse::Middleware::BodyBuilder
159
+ # @see Parse::Middleware::Caching
160
+ # @see Parse::Middleware::Authentication
161
+ # @see Parse::Protocol
142
162
  def setup(opts = {})
143
163
  @clients[:default] = self.new(opts, &Proc.new)
144
164
  end
145
165
 
146
166
  end
147
167
 
148
- # This builds a new Parse::Client stack. The options are:
149
- # required
150
- # :application_id - Parse Application ID. If not set it will be read from the
151
- # PARSE_APP_ID environment variable
152
- # :api_key - the Parse REST API Key. If not set it will be
153
- # read from PARSE_API_KEY environment variable
154
- # :master_key - the Parse Master Key (optional). If PARSE_MASTER_KEY env is set
155
- # it will be used.
156
- # optional
157
- # :logger - boolean - whether to print the requests and responses.
158
- # :cache - Moneta::Transformer - if set, it should be a Moneta store instance
159
- # :expires - Integer - if set, it should be a Moneta store instance
160
- # :adapter - the HTTP adapter to use with Faraday, defaults to Faraday.default_adapter
161
- # :host - defaults to Parse::Protocol::SERVER_URL (https://api.parse.com/1/)
168
+ # Create a new client connected to the Parse Server REST API endpoint.
169
+ # @param opts [Hash] a set of connection options to configure the client.
170
+ # @option opts [String] :server_url The server url of your Parse Server if you
171
+ # are not using the hosted Parse service. By default it will use
172
+ # PARSE_SERVER_URL environment variable available or fall back to
173
+ # https://api.parse.com/1/ if not specified.
174
+ # @option opts [String] :app_id The Parse application id. By default it will
175
+ # use PARSE_APP_ID environment variable if not specified.
176
+ # @option opts [String] :api_key The Parse REST API Key. By default it will
177
+ # use PARSE_API_KEY environment variable if not specified.
178
+ # @option opts [String] :master_key The Parse application master key (optional).
179
+ # If this key is set, it will be sent on every request sent by the client
180
+ # and your models. By default it will use PARSE_MASTER_KEY environment
181
+ # variable if not specified.
182
+ # @option opts [Boolean] :logging It provides you additional logging information
183
+ # of requests and responses. If set to the special symbol of *:debug*, it
184
+ # will provide additional payload data in the log messages. This option affects
185
+ # the logging performed by {Parse::Middleware::BodyBuilder}.
186
+ # @option opts [Object] :adapter The connection adapter. By default it uses
187
+ # the `Faraday.default_adapter` which is Net/HTTP.
188
+ # @option opts [Moneta::Transformer] :cache A caching adapter of type
189
+ # {https://github.com/minad/moneta Moneta::Transformer} that will be used
190
+ # by the caching middleware {Parse::Middleware::Caching}.
191
+ # Caching queries and object fetches can help improve the performance of
192
+ # your application, even if it is for a few seconds. Only successful GET
193
+ # object fetches and non-empty result queries will be cached by default.
194
+ # You may set the default expiration time with the expires option.
195
+ # At any point in time you may clear the cache by calling the {Parse::Client#clear_cache!}
196
+ # method on the client connection. See {https://github.com/minad/moneta Moneta}.
197
+ # @option opts [Integer] :expires Sets the default cache expiration time
198
+ # (in seconds) for successful non-empty GET requests when using the caching
199
+ # middleware. The default value is 3 seconds. If :expires is set to 0,
200
+ # caching will be disabled. You can always clear the current state of the
201
+ # cache using the clear_cache! method on your Parse::Client instance.
202
+ # @option opts [Hash] :faraday You may pass a hash of options that will be
203
+ # passed to the Faraday constructor.
204
+ # @raise ArgumentError if the cache instance passed to the :cache option is not of Moneta::Transformer.
205
+ # @see Parse::Middleware::BodyBuilder
206
+ # @see Parse::Middleware::Caching
207
+ # @see Parse::Middleware::Authentication
208
+ # @see Parse::Protocol
162
209
  def initialize(opts = {})
163
210
  @server_url = opts[:server_url] || ENV["PARSE_SERVER_URL"] || Parse::Protocol::SERVER_URL
164
211
  @application_id = opts[:application_id] || opts[:app_id] || ENV["PARSE_APP_ID"] || ENV['PARSE_SERVER_APPLICATION_ID']
@@ -211,7 +258,6 @@ module Parse
211
258
 
212
259
  end
213
260
  Parse::Client.clients[:default] ||= self
214
- self
215
261
  end
216
262
 
217
263
  # @return [String] the url prefix of the Parse Server url.
@@ -224,17 +270,62 @@ module Parse
224
270
  self.cache.clear if self.cache.present?
225
271
  end
226
272
 
227
- # This is the base method to make raw requests. The first parameter is a symbol
228
- # of the type of request - either :get, :put, :post, :delete. The second parameter
229
- # is the path api to use. For example, to make a request for objects, you would pass the "/1/classes/<ClassName>".
230
- # After the first two parameters, the rest are named parameters. If the request is of type :get, you can pass
231
- # any query string parameters in hash form with query:. If it is any other request, the body of the request should be sent
232
- # with the body: parameter. Note that the middleware will handle turning the hash sent into the body: parameter into JSON.
233
- # If you need to override or add additional headers to a specific request (ex. when uploading a Parse File), you can do so
234
- # with the header: paramter (also a hash).
235
- # This method also takes in a Parse::Request object instead of the arguments listed above.
273
+ # Send a REST API request to the server. This is the low-level API used for all requests
274
+ # to the Parse server with the provided options. Every request sent to Parse through
275
+ # the client goes through the configured set of middleware that can be modified by applying
276
+ # different headers or specific options.
277
+ # This method supports retrying requests a few times when a {Parse::ServiceUnavailableError}
278
+ # is raised.
279
+ # @param method [Symbol] The method type of the HTTP request (ex. :get, :post).
280
+ # - This parameter can also be a {Parse::Request} object.
281
+ # @param uri [String] the url path. It should not be an absolute url.
282
+ # @param body [Hash] the body of the request.
283
+ # @param query [Hash] the set of url query parameters to use in a GET request.
284
+ # @param headers [Hash] additional headers to apply to this request.
285
+ # @param opts [Hash] a set of options to pass through the middleware stack.
286
+ # - *:cache* [Integer] the number of seconds to cache this specific request.
287
+ # If set to `false`, caching will be disabled completely all together, which means even if
288
+ # a cached response exists, it will not be used.
289
+ # - *:use_master_key* [Boolean] whether this request should send the master key, if
290
+ # it was configured with {Parse.setup}. By default, if a master key was configured,
291
+ # all outgoing requests will contain it in the request header. Default `true`.
292
+ # - *:session_token* [String] The session token to send in this request. This disables
293
+ # sending the master key in the request, and sends this request with the credentials provided by
294
+ # the session_token.
295
+ # - *:retry* [Integer] The number of retrties to perform if the service is unavailable.
296
+ # Set to false to disable the retry mechanism. When performing request retries, the
297
+ # client will sleep for a number of seconds ({Parse::Client::RETRY_DELAY}) between requests.
298
+ # The default value is {Parse::Client::RETRY_COUNT}.
299
+ # @raise Parse::AuthenticationError when HTTP response status is 401 or 403
300
+ # @raise Parse::TimeoutError when HTTP response status is 400 or
301
+ # 408, and the Parse code is 143 or {Parse::Response::ERROR_TIMEOUT}.
302
+ # @raise Parse::ConnectionError when HTTP response status is 404 is not an object not found error.
303
+ # - This will also be raised if after retrying a request a number of times has finally failed.
304
+ # @raise Parse::ProtocolError when HTTP response status is 405 or 406
305
+ # @raise Parse::ServiceUnavailableError when HTTP response status is 500 or 503.
306
+ # - This may also happen when the Parse Server response code is any
307
+ # number less than {Parse::Response::ERROR_SERVICE_UNAVAILABLE}.
308
+ # @raise Parse::ServerError when the Parse response code is less than 100
309
+ # @raise Parse::RequestLimitExceededError when the Parse response code is {Parse::Response::ERROR_EXCEEDED_BURST_LIMIT}.
310
+ # - This usually means you have exceeded the burst limit on requests, which will mean you will be throttled for the
311
+ # next 60 seconds.
312
+ # @raise Parse::InvalidSessionTokenError when the Parse response code is 209.
313
+ # - This means the session token that was sent in the request seems to be invalid.
314
+ # @return [Parse::Response] the response for this request.
315
+ # @see Parse::Middleware::BodyBuilder
316
+ # @see Parse::Middleware::Caching
317
+ # @see Parse::Middleware::Authentication
318
+ # @see Parse::Protocol
319
+ # @see Parse::Request
236
320
  def request(method, uri = nil, body: nil, query: nil, headers: nil, opts: {})
237
321
  retry_count ||= RETRY_COUNT
322
+
323
+ if opts[:retry] == false
324
+ retry_count = 0
325
+ elsif opts[:retry].to_i > 0
326
+ retry_count = opts[:retry]
327
+ end
328
+
238
329
  headers ||= {}
239
330
  # if the first argument is a Parse::Request object, then construct it
240
331
  _request = nil
@@ -297,16 +388,13 @@ module Parse
297
388
  when 405, 406
298
389
  puts "[Parse:ProtocolError] #{response}"
299
390
  raise Parse::ProtocolError, response
300
- when 500
301
- puts "[Parse:ServiceUnavailableError] #{response}"
302
- raise Parse::ServiceUnavailableError, response
303
- when 503
391
+ when 500, 503
304
392
  puts "[Parse:ServiceUnavailableError] #{response}"
305
393
  raise Parse::ServiceUnavailableError, response
306
394
  end
307
395
 
308
396
  if response.error?
309
- if response.code <= Parse::Response::ERROR_SERVICE_UNAVAILALBE
397
+ if response.code <= Parse::Response::ERROR_SERVICE_UNAVAILABLE
310
398
  puts "[Parse:ServiceUnavailableError] #{response}"
311
399
  raise Parse::ServiceUnavailableError, response
312
400
  elsif response.code <= 100
@@ -315,7 +403,7 @@ module Parse
315
403
  elsif response.code == Parse::Response::ERROR_EXCEEDED_BURST_LIMIT
316
404
  puts "[Parse:RequestLimitExceededError] #{response}"
317
405
  raise Parse::RequestLimitExceededError, response
318
- elsif response.code == 209 #Error 209: invalid session token
406
+ elsif response.code == 209 # Error 209: invalid session token
319
407
  puts "[Parse:InvalidSessionTokenError] #{response}"
320
408
  raise Parse::InvalidSessionTokenError, response
321
409
  end
@@ -329,7 +417,7 @@ module Parse
329
417
  retry_count -= 1
330
418
  retry
331
419
  end
332
- raise e
420
+ raise
333
421
  rescue Faraday::Error::ClientError, Net::OpenTimeout => e
334
422
  if retry_count > 0
335
423
  puts "[Parse:Retry] Retries remaining #{retry_count} : #{_request}"
@@ -340,26 +428,46 @@ module Parse
340
428
  raise Parse::ConnectionError, "#{_request} : #{e.class} - #{e.message}"
341
429
  end
342
430
 
343
- # shorthand for request(:get, uri, query: {})
431
+ # Send a GET request.
432
+ # @param uri [String] the uri path for this request.
433
+ # @param query [Hash] the set of url query parameters.
434
+ # @param headers [Hash] additional headers to send in this request.
435
+ # @return (see #request)
344
436
  def get(uri, query = nil, headers = {})
345
437
  request :get, uri, query: query, headers: headers
346
438
  end
347
439
 
348
- # shorthand for request(:post, uri, body: {})
440
+ # Send a POST request.
441
+ # @param uri (see #get)
442
+ # @param body [Hash] a hash that will be JSON encoded for the body of this request.
443
+ # @param headers (see #get)
444
+ # @return (see #request)
349
445
  def post(uri, body = nil, headers = {} )
350
446
  request :post, uri, body: body, headers: headers
351
447
  end
352
448
 
353
- # shorthand for request(:put, uri, body: {})
449
+ # Send a PUT request.
450
+ # @param uri (see #post)
451
+ # @param body (see #post)
452
+ # @param headers (see #post)
453
+ # @return (see #request)
354
454
  def put(uri, body = nil, headers = {})
355
455
  request :put, uri, body: body, headers: headers
356
456
  end
357
457
 
358
- # shorthand for request(:delete, uri, body: {}, headers: {})
458
+ # Send a DELETE request.
459
+ # @param uri (see #post)
460
+ # @param body (see #post)
461
+ # @param headers (see #post)
462
+ # @return (see #request)
359
463
  def delete(uri, body = nil, headers = {})
360
464
  request :delete, uri, body: body, headers: headers
361
465
  end
362
466
 
467
+ # Send a {Parse::Request} object.
468
+ # @param req [Parse::Request] the request to send
469
+ # @raise ArgumentError if req is not of type Parse::Request.
470
+ # @return (see #request)
363
471
  def send_request(req) #Parse::Request object
364
472
  raise ArgumentError, "Object not of Parse::Request type." unless req.is_a?(Parse::Request)
365
473
  request req.method, req.path, req.body, req.headers
@@ -376,12 +484,15 @@ module Parse
376
484
  end
377
485
 
378
486
  module ClassMethods
487
+
488
+ # @return [Parse::Client] the current client for :default.
379
489
  attr_accessor :client
380
490
  def client
381
491
  @client ||= Parse::Client.client #defaults to :default tag
382
492
  end
383
493
  end
384
494
 
495
+ # @return [Parse::Client] the current client defined for the class.
385
496
  def client
386
497
  self.class.client
387
498
  end
@@ -391,6 +502,16 @@ module Parse
391
502
 
392
503
  # Helper method that users should call to setup the client stack.
393
504
  # A block can be passed in order to do additional client configuration.
505
+ # To connect to a Parse server, you will need a minimum of an application_id,
506
+ # an api_key and a server_url. To connect to the server endpoint, you use the
507
+ # {Parse.setup} method below.
508
+ #
509
+ # @example (see Parse::Client.setup)
510
+ # @param opts (see Parse::Client.setup)
511
+ # @option opts (see Parse::Client.setup)
512
+ # @yield (see Parse::Client.setup)
513
+ # @return (see Parse::Client.setup)
514
+ # @see Parse::Client.setup
394
515
  def self.setup(opts = {})
395
516
  if block_given?
396
517
  Parse::Client.new(opts, &Proc.new)
@@ -399,7 +520,11 @@ module Parse
399
520
  end
400
521
  end
401
522
 
402
- # Helper method to call cloud functions and get results
523
+ # Helper method to trigger cloud jobs and get results.
524
+ # @param name [String] the name of the cloud code job to trigger.
525
+ # @param body [Hash] the set of parameters to pass to the job.
526
+ # @param opts (see Parse.call_function)
527
+ # @return (see Parse.call_function)
403
528
  def self.trigger_job(name, body = {}, **opts)
404
529
  conn = opts[:session] || opts[:client] || :default
405
530
  response = Parse::Client.client(conn).trigger_job(name, body)
@@ -407,7 +532,11 @@ module Parse
407
532
  response.error? ? nil : response.result["result"]
408
533
  end
409
534
 
410
- # Helper method to call cloud functions and get results
535
+ # Helper method to call cloud functions and get results.
536
+ # @param name [String] the name of the cloud code function to call.
537
+ # @param body [Hash] the set of parameters to pass to the function.
538
+ # @param opts [Hash] additional options.
539
+ # @return [Object] the result data of the response. nil if there was an error.
411
540
  def self.call_function(name, body = {}, **opts)
412
541
  conn = opts[:session] || opts[:client] || :default
413
542
  response = Parse::Client.client(conn).call_function(name, body)