parse-ruby-client 0.1.8 → 0.1.9

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.
@@ -0,0 +1,62 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://api.parse.com/1/batch
6
+ body:
7
+ encoding: UTF-8
8
+ string: "{\"requests\":[{\"method\":\"POST\",\"path\":\"/1/classes/GameScore\",\"body\":{\"gameScore\":42}}]}"
9
+ headers:
10
+ Content-Type:
11
+ - application/json
12
+ Accept:
13
+ - application/json
14
+ User-Agent:
15
+ - Parse for Ruby, 0.0
16
+ X-Parse-Master-Key:
17
+ - ""
18
+ X-Parse-Rest-Api-Key:
19
+ - jYdptjS76YHikuIFfJEgHD8UMIjH6cp2rWz4fo2C
20
+ X-Parse-Application-Id:
21
+ - hnJRtntbYPvWfjqcqLZsdFaOKT0F3SfNU7Kc7woN
22
+ X-Parse-Session-Token:
23
+ - ""
24
+ Expect:
25
+ - ""
26
+ response:
27
+ status:
28
+ code: 200
29
+ message: OK
30
+ headers:
31
+ Access-Control-Allow-Origin:
32
+ - "*"
33
+ Access-Control-Request-Method:
34
+ - "*"
35
+ Cache-Control:
36
+ - max-age=0, private, must-revalidate
37
+ Content-Type:
38
+ - application/json; charset=utf-8
39
+ Date:
40
+ - Tue, 08 Jan 2013 15:12:42 GMT
41
+ Etag:
42
+ - "\"98e77897bd1902cdc3885b7f63ba4765\""
43
+ Server:
44
+ - nginx/1.2.2
45
+ Set-Cookie:
46
+ - _parse_session=BAh7BkkiD3Nlc3Npb25faWQGOgZFRiIlYmZjMTc1NWY3MzhkMzY4ZTFlNzA2OTJhNWVmODAxY2I%3D--c18a9b64bbafbd180ba894073d8e6452ee909d69; domain=.parse.com; path=/; expires=Sun, 08-Jan-2023 15:12:42 GMT; secure; HttpOnly
47
+ Status:
48
+ - 200 OK
49
+ X-Runtime:
50
+ - "18.138760"
51
+ X-Ua-Compatible:
52
+ - IE=Edge,chrome=1
53
+ Content-Length:
54
+ - "78"
55
+ Connection:
56
+ - keep-alive
57
+ body:
58
+ encoding: ASCII-8BIT
59
+ string: "[{\"success\":{\"createdAt\":\"2013-01-08T15:12:26.671Z\",\"objectId\":\"YwUiZtIHgm\"}}]"
60
+ http_version:
61
+ recorded_at: Tue, 08 Jan 2013 15:12:44 GMT
62
+ recorded_with: VCR 2.0.1
@@ -12,10 +12,42 @@ module Parse
12
12
  @requests << request
13
13
  end
14
14
 
15
+ def create_object(object)
16
+ method = "POST"
17
+ path = Parse::Protocol.class_uri(object.class_name)
18
+ body = object.safe_hash
19
+ add_request({
20
+ "method" => method,
21
+ "path" => path,
22
+ "body" => body
23
+ })
24
+ end
25
+
26
+ def update_object(object)
27
+ method = "PUT"
28
+ path = Parse::Protocol.class_uri(object.class_name, object.id)
29
+ body = object.safe_hash
30
+ add_request({
31
+ "method" => method,
32
+ "path" => path,
33
+ "body" => body
34
+ })
35
+ end
36
+
37
+ def delete_object(object)
38
+ add_request({
39
+ "method" => "DELETE",
40
+ "path" => Parse::Protocol.class_uri(object.class_name, object.id)
41
+ })
42
+ end
43
+
15
44
  def run!
16
45
  uri = Parse::Protocol.batch_request_uri
17
46
  body = {:requests => @requests}.to_json
18
47
  Parse.client.request(uri, :post, body)
19
48
  end
49
+
50
+
20
51
  end
52
+
21
53
  end
@@ -8,6 +8,8 @@ module Parse
8
8
  # API server. Currently uses the Patron library for low-level HTTP
9
9
  # communication.
10
10
  class Client
11
+ DEFAULT_RETRIES = 2
12
+
11
13
  attr_accessor :host
12
14
  attr_accessor :application_id
13
15
  attr_accessor :api_key
@@ -35,7 +37,7 @@ module Parse
35
37
  # with common basic response handling. Will raise a
36
38
  # ParseProtocolError if the response has an error status code,
37
39
  # and will return the parsed JSON body on success, if there is one.
38
- def request(uri, method = :get, body = nil, query = nil, max_retries = 2)
40
+ def request(uri, method = :get, body = nil, query = nil, max_retries = DEFAULT_RETRIES)
39
41
  @session.headers[Protocol::HEADER_MASTER_KEY] = @master_key
40
42
  @session.headers[Protocol::HEADER_API_KEY] = @api_key
41
43
  @session.headers[Protocol::HEADER_APP_ID] = @application_id
@@ -51,22 +53,21 @@ module Parse
51
53
 
52
54
  num_tries = 0
53
55
  begin
54
- response = @session.request(method, uri, {}, options)
55
- rescue Patron::TimeoutError
56
56
  num_tries += 1
57
- if num_tries <= max_retries
58
- retry
59
- else
60
- raise Patron::TimeoutError
61
- end
62
- end
57
+ response = @session.request(method, uri, {}, options)
58
+ parsed = JSON.parse(response.body)
63
59
 
64
- if response.status >= 400
65
- raise ParseError, "#{JSON.parse(response.body)['code']}: #{JSON.parse(response.body)['error']}"
66
- else
67
- if response
68
- return JSON.parse response.body
60
+ if response.status >= 400
61
+ raise ParseProtocolError.new(parsed)
69
62
  end
63
+
64
+ return parsed
65
+ rescue Patron::TimeoutError
66
+ retry if num_tries <= max_retries
67
+ raise
68
+ rescue ParseProtocolError => e
69
+ retry if e.code == Protocol::ERROR_TIMEOUT && num_tries <= max_retries
70
+ raise
70
71
  end
71
72
  end
72
73
 
@@ -8,12 +8,18 @@ module Parse
8
8
  class Pointer
9
9
  attr_accessor :parse_object_id
10
10
  attr_accessor :class_name
11
+ alias :id :parse_object_id
11
12
 
12
13
  def initialize(data)
13
14
  @class_name = data[Protocol::KEY_CLASS_NAME]
14
15
  @parse_object_id = data[Protocol::KEY_OBJECT_ID]
15
16
  end
16
17
 
18
+ # make it easier to deal with the ambiguity of whether you're passed a pointer or object
19
+ def pointer
20
+ self
21
+ end
22
+
17
23
  def eql?(other)
18
24
  self.class.equal?(other.class) &&
19
25
  class_name == other.class_name &&
@@ -15,15 +15,12 @@ module Parse
15
15
  attr_accessor :response
16
16
 
17
17
  def initialize(response)
18
- #@response = response
19
- #if response.body
20
- # data = JSON.parse response.body
21
- # @code = data["code"]
22
- # @message = data["error"]
23
- #end
24
-
25
- #{}"#{@code}: #{@message}"
18
+ @response = response
19
+ @code = response["code"]
20
+ @error = response["error"]
21
+
22
+ super("#{@code}: #{@error}")
26
23
  end
27
24
  end
28
-
25
+
29
26
  end
@@ -28,6 +28,11 @@ module Parse
28
28
  Parse::Pointer.new(self.merge(Parse::Protocol::KEY_CLASS_NAME => class_name)) unless new?
29
29
  end
30
30
 
31
+ # make it easier to deal with the ambiguity of whether you're passed a pointer or object
32
+ def get
33
+ self
34
+ end
35
+
31
36
  # Merge a hash parsed from the JSON representation into
32
37
  # this instance. This will extract the reserved fields,
33
38
  # merge the hash keys, and then ensure that the reserved
@@ -63,7 +68,7 @@ module Parse
63
68
  self["objectId"].nil?
64
69
  end
65
70
 
66
- def safe_json
71
+ def safe_hash
67
72
  without_reserved = self.dup
68
73
  Protocol::RESERVED_KEYS.each { |k| without_reserved.delete(k) }
69
74
 
@@ -76,7 +81,11 @@ module Parse
76
81
  end
77
82
  }
78
83
 
79
- without_relations.to_json
84
+ without_relations
85
+ end
86
+
87
+ def safe_json
88
+ safe_hash.to_json
80
89
  end
81
90
 
82
91
  private :parse
@@ -124,6 +124,8 @@ module Parse
124
124
 
125
125
  BATCH_REQUEST_URI = "batch"
126
126
 
127
+ ERROR_TIMEOUT = 124
128
+
127
129
  # URI Helpers
128
130
  # ----------------------------------------
129
131
 
@@ -39,7 +39,7 @@ module Parse
39
39
  add_constraint field, value
40
40
  self
41
41
  end
42
-
42
+
43
43
  def not_eq(field, value)
44
44
  add_constraint field, { "$ne" => value }
45
45
  self
@@ -75,6 +75,11 @@ module Parse
75
75
  self
76
76
  end
77
77
 
78
+ def value_not_in(field, values)
79
+ add_constraint field, { "$nin" => values }
80
+ self
81
+ end
82
+
78
83
  def exists(field, value = true)
79
84
  add_constraint field, { "$exists" => value }
80
85
  self
@@ -86,12 +91,12 @@ module Parse
86
91
  self
87
92
  end
88
93
 
89
- def limit(num)
94
+ def set_limit(num)
90
95
  @limit = num
91
96
  self
92
97
  end
93
98
 
94
- def order(field, order = :ascending)
99
+ def set_order(field, order = :ascending)
95
100
  @order_by = field
96
101
  @order = order
97
102
  self
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "parse-ruby-client"
8
- s.version = "0.1.8"
8
+ s.version = "0.1.9"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Alan deLevie", "Adam Alpern"]
12
- s.date = "2013-01-05"
12
+ s.date = "2013-01-10"
13
13
  s.description = "A simple Ruby client for the parse.com REST API"
14
14
  s.email = "adelevie@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -26,7 +26,10 @@ Gem::Specification.new do |s|
26
26
  "VERSION",
27
27
  "example.rb",
28
28
  "fixtures/vcr_cassettes/test_array_add.yml",
29
+ "fixtures/vcr_cassettes/test_batch_create_object.yml",
30
+ "fixtures/vcr_cassettes/test_batch_delete_object.yml",
29
31
  "fixtures/vcr_cassettes/test_batch_run.yml",
32
+ "fixtures/vcr_cassettes/test_batch_update_object.yml",
30
33
  "fixtures/vcr_cassettes/test_cloud_function.yml",
31
34
  "fixtures/vcr_cassettes/test_created_at.yml",
32
35
  "fixtures/vcr_cassettes/test_deep_parse.yml",
@@ -38,6 +41,7 @@ Gem::Specification.new do |s|
38
41
  "fixtures/vcr_cassettes/test_object_id.yml",
39
42
  "fixtures/vcr_cassettes/test_parse_delete.yml",
40
43
  "fixtures/vcr_cassettes/test_pointer.yml",
44
+ "fixtures/vcr_cassettes/test_request_batch.yml",
41
45
  "fixtures/vcr_cassettes/test_server_update.yml",
42
46
  "fixtures/vcr_cassettes/test_simple_save.yml",
43
47
  "fixtures/vcr_cassettes/test_update.yml",
@@ -56,4 +56,60 @@ class TestBatch < Test::Unit::TestCase
56
56
  end
57
57
  end
58
58
 
59
+ def test_create_object
60
+ VCR.use_cassette('test_batch_create_object', :record => :new_episodes) do
61
+ objects = [1, 2, 3, 4, 5].map do |i|
62
+ p = Parse::Object.new("BatchTestObject")
63
+ p["foo"] = "#{i}"
64
+ p
65
+ end
66
+ batch = Parse::Batch.new
67
+ objects.each do |obj|
68
+ batch.create_object(obj)
69
+ end
70
+ resp = batch.run!
71
+ assert_equal Array, resp.class
72
+ assert_equal resp.first["success"]["objectId"].class, String
73
+ end
74
+ end
75
+
76
+ def test_update_object
77
+ VCR.use_cassette('test_batch_update_object', :record => :new_episodes) do
78
+ objects = [1, 2, 3, 4, 5].map do |i|
79
+ p = Parse::Object.new("BatchTestObject")
80
+ p["foo"] = "#{i}"
81
+ p.save
82
+ p
83
+ end
84
+ objects.map do |obj|
85
+ obj["foo"] = "updated"
86
+ end
87
+ batch = Parse::Batch.new
88
+ objects.each do |obj|
89
+ batch.update_object(obj)
90
+ end
91
+ resp = batch.run!
92
+ assert_equal Array, resp.class
93
+ assert_equal resp.first["success"]["updatedAt"].class, String
94
+ end
95
+ end
96
+
97
+ def test_delete_object
98
+ VCR.use_cassette('test_batch_delete_object', :record => :new_episodes) do
99
+ objects = [1, 2, 3, 4, 5].map do |i|
100
+ p = Parse::Object.new("BatchTestObject")
101
+ p["foo"] = "#{i}"
102
+ p.save
103
+ p
104
+ end
105
+ batch = Parse::Batch.new
106
+ objects.each do |obj|
107
+ batch.delete_object(obj)
108
+ end
109
+ resp = batch.run!
110
+ assert_equal Array, resp.class
111
+ assert_equal resp.first["success"], true
112
+ end
113
+ end
114
+
59
115
  end
@@ -2,7 +2,19 @@ require 'helper'
2
2
 
3
3
  class TestClient < Test::Unit::TestCase
4
4
  def setup
5
- Parse.init
5
+ @client = Parse.init
6
+ end
7
+
8
+ def test_request
9
+ VCR.use_cassette('test_request', :record => :new_episodes) do
10
+ response = mock()
11
+ response.stubs(:body).returns({'code' => Parse::Protocol::ERROR_TIMEOUT}.to_json)
12
+ response.stubs(:status).returns(400)
13
+ @client.session.expects(:request).times(Parse::Client::DEFAULT_RETRIES + 1).returns(response)
14
+ assert_raise do
15
+ @client.request(nil)
16
+ end
17
+ end
6
18
  end
7
19
 
8
20
  def test_simple_save
@@ -69,7 +69,7 @@ class TestObject < Test::Unit::TestCase
69
69
 
70
70
  post.parse_delete
71
71
 
72
- assert_raise Parse::ParseError do
72
+ assert_raise Parse::ParseProtocolError do
73
73
  q = Parse.get("Post", post.id)
74
74
  end
75
75
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parse-ruby-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.1.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-01-05 00:00:00.000000000 Z
13
+ date: 2013-01-10 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: patron
@@ -173,7 +173,10 @@ files:
173
173
  - VERSION
174
174
  - example.rb
175
175
  - fixtures/vcr_cassettes/test_array_add.yml
176
+ - fixtures/vcr_cassettes/test_batch_create_object.yml
177
+ - fixtures/vcr_cassettes/test_batch_delete_object.yml
176
178
  - fixtures/vcr_cassettes/test_batch_run.yml
179
+ - fixtures/vcr_cassettes/test_batch_update_object.yml
177
180
  - fixtures/vcr_cassettes/test_cloud_function.yml
178
181
  - fixtures/vcr_cassettes/test_created_at.yml
179
182
  - fixtures/vcr_cassettes/test_deep_parse.yml
@@ -185,6 +188,7 @@ files:
185
188
  - fixtures/vcr_cassettes/test_object_id.yml
186
189
  - fixtures/vcr_cassettes/test_parse_delete.yml
187
190
  - fixtures/vcr_cassettes/test_pointer.yml
191
+ - fixtures/vcr_cassettes/test_request_batch.yml
188
192
  - fixtures/vcr_cassettes/test_server_update.yml
189
193
  - fixtures/vcr_cassettes/test_simple_save.yml
190
194
  - fixtures/vcr_cassettes/test_update.yml
@@ -233,7 +237,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
233
237
  version: '0'
234
238
  segments:
235
239
  - 0
236
- hash: 3206718523214024845
240
+ hash: -4088256364268233622
237
241
  required_rubygems_version: !ruby/object:Gem::Requirement
238
242
  none: false
239
243
  requirements: