parse-ruby-client 0.1.14 → 0.1.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/.travis.yml +3 -2
  2. data/Gemfile +12 -12
  3. data/Gemfile.lock +26 -12
  4. data/OLD_README.md +255 -0
  5. data/README.md +1038 -144
  6. data/Rakefile +2 -10
  7. data/VERSION +1 -1
  8. data/features.md +11 -11
  9. data/fixtures/vcr_cassettes/test_acls_arent_objects.yml +180 -0
  10. data/fixtures/vcr_cassettes/test_array_add.yml +20 -20
  11. data/fixtures/vcr_cassettes/test_array_add_pointerizing.yml +239 -0
  12. data/fixtures/vcr_cassettes/test_array_add_unique.yml +180 -0
  13. data/fixtures/vcr_cassettes/test_batch_create_object.yml +53 -80
  14. data/fixtures/vcr_cassettes/test_batch_delete_object.yml +303 -428
  15. data/fixtures/vcr_cassettes/test_batch_run.yml +53 -74
  16. data/fixtures/vcr_cassettes/test_batch_update_object.yml +303 -432
  17. data/fixtures/vcr_cassettes/test_circular_save.yml +121 -0
  18. data/fixtures/vcr_cassettes/test_created_at.yml +53 -74
  19. data/fixtures/vcr_cassettes/test_decrement.yml +121 -0
  20. data/fixtures/vcr_cassettes/test_deep_parse.yml +154 -218
  21. data/fixtures/vcr_cassettes/test_destroy.yml +104 -144
  22. data/fixtures/vcr_cassettes/test_eq_pointerize.yml +239 -0
  23. data/fixtures/vcr_cassettes/test_equality.yml +180 -0
  24. data/fixtures/vcr_cassettes/test_get.yml +104 -146
  25. data/fixtures/vcr_cassettes/test_get_missing.yml +60 -0
  26. data/fixtures/vcr_cassettes/test_include.yml +27 -27
  27. data/fixtures/vcr_cassettes/test_new_model.yml +53 -146
  28. data/fixtures/vcr_cassettes/test_new_object.yml +53 -74
  29. data/fixtures/vcr_cassettes/test_nils_delete_keys.yml +155 -216
  30. data/fixtures/vcr_cassettes/test_parse_delete.yml +204 -284
  31. data/fixtures/vcr_cassettes/test_pointer.yml +53 -74
  32. data/fixtures/vcr_cassettes/test_save_with_sub_objects.yml +298 -0
  33. data/fixtures/vcr_cassettes/test_saving_boolean_values.yml +121 -0
  34. data/fixtures/vcr_cassettes/test_server_update.yml +257 -358
  35. data/fixtures/vcr_cassettes/test_simple_save.yml +53 -74
  36. data/fixtures/vcr_cassettes/test_text_file_save.yml +53 -161
  37. data/fixtures/vcr_cassettes/test_update.yml +104 -144
  38. data/fixtures/vcr_cassettes/test_updated_at.yml +104 -144
  39. data/fixtures/vcr_cassettes/test_user_save.yml +10 -10
  40. data/lib/parse/client.rb +43 -6
  41. data/lib/parse/datatypes.rb +14 -35
  42. data/lib/parse/error.rb +8 -0
  43. data/lib/parse/object.rb +25 -20
  44. data/lib/parse/protocol.rb +3 -4
  45. data/lib/parse/query.rb +10 -9
  46. data/lib/parse/util.rb +36 -2
  47. data/parse-ruby-client.gemspec +22 -18
  48. data/test/helper.rb +33 -5
  49. data/test/test_batch.rb +1 -4
  50. data/test/test_client.rb +59 -7
  51. data/test/test_cloud.rb +3 -7
  52. data/test/test_datatypes.rb +6 -7
  53. data/test/test_file.rb +9 -10
  54. data/test/test_model.rb +1 -4
  55. data/test/test_object.rb +148 -6
  56. data/test/test_push.rb +1 -5
  57. data/test/test_query.rb +13 -3
  58. data/test/test_throttle.rb +1 -3
  59. data/test/test_user.rb +1 -5
  60. metadata +23 -19
  61. data/fixtures/vcr_cassettes/test_array_add_relation.yml +0 -321
  62. data/fixtures/vcr_cassettes/test_cloud_function.yml +0 -81
  63. data/fixtures/vcr_cassettes/test_file_save.yml +0 -87
  64. data/fixtures/vcr_cassettes/test_image_file_associate_with_object.yml +0 -2034
  65. data/fixtures/vcr_cassettes/test_image_file_save.yml +0 -1957
  66. data/fixtures/vcr_cassettes/test_object_id.yml +0 -83
  67. data/fixtures/vcr_cassettes/test_request_batch.yml +0 -62
@@ -1,161 +1,121 @@
1
- ---
2
- http_interactions:
3
- - request:
1
+ ---
2
+ http_interactions:
3
+ - request:
4
4
  method: post
5
5
  uri: https://api.parse.com/1/classes/Post
6
- body:
6
+ body:
7
7
  encoding: UTF-8
8
- string: ! '{"title":"hello"}'
9
- headers:
10
- Content-Type:
8
+ string: "{\"title\":\"hello\"}"
9
+ headers:
10
+ Content-Type:
11
11
  - application/json
12
- Accept:
12
+ Accept:
13
13
  - application/json
14
- User-Agent:
14
+ User-Agent:
15
15
  - Parse for Ruby, 0.0
16
- X-Parse-Master-Key:
17
- - ''
18
- X-Parse-Rest-Api-Key:
19
- - D3Y8jNCQk6kpkKhpRGnWLYTrFGQ7j8dtDVnWZRnZ
20
- X-Parse-Application-Id:
21
- - PPVk6L5M9R1R8GVk8Ye9jT8f5SQNBIeoJUDJLmkT
22
- X-Parse-Session-Token:
23
- - ''
24
- Expect:
25
- - ''
26
- response:
27
- status:
16
+ X-Parse-Master-Key:
17
+ - ""
18
+ X-Parse-Rest-Api-Key:
19
+ - <X-Parse-REST-API-Key>
20
+ X-Parse-Application-Id:
21
+ - <X-Parse-Application-Id>
22
+ X-Parse-Session-Token:
23
+ - ""
24
+ Expect:
25
+ - ""
26
+ response:
27
+ status:
28
28
  code: 201
29
- message: !binary |-
30
- Q3JlYXRlZA==
31
- headers:
32
- !binary "QWNjZXNzLUNvbnRyb2wtQWxsb3ctT3JpZ2lu":
33
- - !binary |-
34
- Kg==
35
- !binary "QWNjZXNzLUNvbnRyb2wtUmVxdWVzdC1NZXRob2Q=":
36
- - !binary |-
37
- Kg==
38
- !binary "Q2FjaGUtQ29udHJvbA==":
39
- - !binary |-
40
- bm8tY2FjaGU=
41
- !binary "Q29udGVudC1UeXBl":
42
- - !binary |-
43
- YXBwbGljYXRpb24vanNvbjsgY2hhcnNldD11dGYtOA==
44
- !binary "RGF0ZQ==":
45
- - !binary |-
46
- VHVlLCAwOSBPY3QgMjAxMiAyMTo0NTozMiBHTVQ=
47
- !binary "TG9jYXRpb24=":
48
- - !binary |-
49
- aHR0cHM6Ly9hcGkucGFyc2UuY29tLzEvY2xhc3Nlcy9Qb3N0LzNiODJoeWI2
50
- UUY=
51
- !binary "U2VydmVy":
52
- - !binary |-
53
- bmdpbngvMS4yLjI=
54
- !binary "U2V0LUNvb2tpZQ==":
55
- - !binary |-
56
- X3BhcnNlX3Nlc3Npb249QkFoN0Jra2lEM05sYzNOcGIyNWZhV1FHT2daRlJp
57
- SWxPR1ZrTVdWbFpqWmpZbU5qWVdNell6Tm1NMk5rTmpoa09UTTFZV1pqTjJZ
58
- JTNELS05N2M1NmUwNDBmMWUyMGQ3MmZlNzA0MGRhOGViZjFlYWM1ZjYwMGNm
59
- OyBkb21haW49LnBhcnNlLmNvbTsgcGF0aD0vOyBleHBpcmVzPVN1biwgMDkt
60
- T2N0LTIwMjIgMjE6NDU6MzIgR01UOyBzZWN1cmU7IEh0dHBPbmx5
61
- !binary "U3RhdHVz":
62
- - !binary |-
63
- MjAxIENyZWF0ZWQ=
64
- !binary "WC1SdW50aW1l":
65
- - !binary |-
66
- MC4wMTg5OTc=
67
- !binary "WC1VYS1Db21wYXRpYmxl":
68
- - !binary |-
69
- SUU9RWRnZSxjaHJvbWU9MQ==
70
- !binary "Q29udGVudC1MZW5ndGg=":
71
- - !binary |-
72
- NjQ=
73
- !binary "Q29ubmVjdGlvbg==":
74
- - !binary |-
75
- a2VlcC1hbGl2ZQ==
76
- body:
29
+ message: Created
30
+ headers:
31
+ Access-Control-Allow-Origin:
32
+ - "*"
33
+ Access-Control-Request-Method:
34
+ - "*"
35
+ Cache-Control:
36
+ - no-cache
37
+ Content-Type:
38
+ - application/json; charset=utf-8
39
+ Date:
40
+ - Mon, 22 Apr 2013 16:03:23 GMT
41
+ Location:
42
+ - https://api.parse.com/1/classes/Post/UzS4Cr4U3J
43
+ Server:
44
+ - nginx/1.2.2
45
+ Set-Cookie:
46
+ - <COOKIE-KEY>
47
+ Status:
48
+ - 201 Created
49
+ X-Runtime:
50
+ - "0.025069"
51
+ X-Ua-Compatible:
52
+ - IE=Edge,chrome=1
53
+ Content-Length:
54
+ - "64"
55
+ Connection:
56
+ - keep-alive
57
+ body:
77
58
  encoding: ASCII-8BIT
78
- string: !binary |-
79
- eyJjcmVhdGVkQXQiOiIyMDEyLTEwLTA5VDIxOjQ1OjMyLjQ4OFoiLCJvYmpl
80
- Y3RJZCI6IjNiODJoeWI2UUYifQ==
59
+ string: "{\"createdAt\":\"2013-04-22T16:03:23.371Z\",\"objectId\":\"UzS4Cr4U3J\"}"
81
60
  http_version:
82
- recorded_at: Tue, 09 Oct 2012 21:45:32 GMT
83
- - request:
61
+ recorded_at: Mon, 22 Apr 2013 16:03:23 GMT
62
+ - request:
84
63
  method: put
85
- uri: https://api.parse.com/1/classes/Post/3b82hyb6QF
86
- body:
64
+ uri: https://api.parse.com/1/classes/Post/UzS4Cr4U3J
65
+ body:
87
66
  encoding: UTF-8
88
- string: ! '{"title":"hello 2"}'
89
- headers:
90
- Content-Type:
67
+ string: "{\"title\":\"hello 2\"}"
68
+ headers:
69
+ Content-Type:
91
70
  - application/json
92
- Accept:
71
+ Accept:
93
72
  - application/json
94
- User-Agent:
73
+ User-Agent:
95
74
  - Parse for Ruby, 0.0
96
- X-Parse-Master-Key:
97
- - ''
98
- X-Parse-Rest-Api-Key:
99
- - D3Y8jNCQk6kpkKhpRGnWLYTrFGQ7j8dtDVnWZRnZ
100
- X-Parse-Application-Id:
101
- - PPVk6L5M9R1R8GVk8Ye9jT8f5SQNBIeoJUDJLmkT
102
- X-Parse-Session-Token:
103
- - ''
104
- Expect:
105
- - ''
106
- response:
107
- status:
75
+ X-Parse-Master-Key:
76
+ - ""
77
+ X-Parse-Rest-Api-Key:
78
+ - <X-Parse-REST-API-Key>
79
+ X-Parse-Application-Id:
80
+ - <X-Parse-Application-Id>
81
+ X-Parse-Session-Token:
82
+ - ""
83
+ Expect:
84
+ - ""
85
+ response:
86
+ status:
108
87
  code: 200
109
- message: !binary |-
110
- T0s=
111
- headers:
112
- !binary "QWNjZXNzLUNvbnRyb2wtQWxsb3ctT3JpZ2lu":
113
- - !binary |-
114
- Kg==
115
- !binary "QWNjZXNzLUNvbnRyb2wtUmVxdWVzdC1NZXRob2Q=":
116
- - !binary |-
117
- Kg==
118
- !binary "Q2FjaGUtQ29udHJvbA==":
119
- - !binary |-
120
- bWF4LWFnZT0wLCBwcml2YXRlLCBtdXN0LXJldmFsaWRhdGU=
121
- !binary "Q29udGVudC1UeXBl":
122
- - !binary |-
123
- YXBwbGljYXRpb24vanNvbjsgY2hhcnNldD11dGYtOA==
124
- !binary "RGF0ZQ==":
125
- - !binary |-
126
- VHVlLCAwOSBPY3QgMjAxMiAyMTo0NTozMiBHTVQ=
127
- !binary "RXRhZw==":
128
- - !binary |-
129
- IjhhZTRmMTQzOGY1ZWM3M2Q1NzkyMDdjZTg5MjVmYTFjIg==
130
- !binary "U2VydmVy":
131
- - !binary |-
132
- bmdpbngvMS4yLjI=
133
- !binary "U2V0LUNvb2tpZQ==":
134
- - !binary |-
135
- X3BhcnNlX3Nlc3Npb249QkFoN0Jra2lEM05sYzNOcGIyNWZhV1FHT2daRlJp
136
- SWxZVFJpTlRabFkyRXpaVGMyWWpCaFl6SmhaV1l6TnpsaE1XTTFaakl6WldZ
137
- JTNELS1hYTJkNjdlN2FkNjZhODBlZGRmMTk5OTJjZjg4YmFiYWU1NDJiNzVm
138
- OyBkb21haW49LnBhcnNlLmNvbTsgcGF0aD0vOyBleHBpcmVzPVN1biwgMDkt
139
- T2N0LTIwMjIgMjE6NDU6MzIgR01UOyBzZWN1cmU7IEh0dHBPbmx5
140
- !binary "U3RhdHVz":
141
- - !binary |-
142
- MjAwIE9L
143
- !binary "WC1SdW50aW1l":
144
- - !binary |-
145
- MC4wMzUwODU=
146
- !binary "WC1VYS1Db21wYXRpYmxl":
147
- - !binary |-
148
- SUU9RWRnZSxjaHJvbWU9MQ==
149
- !binary "Q29udGVudC1MZW5ndGg=":
150
- - !binary |-
151
- NDA=
152
- !binary "Q29ubmVjdGlvbg==":
153
- - !binary |-
154
- a2VlcC1hbGl2ZQ==
155
- body:
88
+ message: OK
89
+ headers:
90
+ Access-Control-Allow-Origin:
91
+ - "*"
92
+ Access-Control-Request-Method:
93
+ - "*"
94
+ Cache-Control:
95
+ - max-age=0, private, must-revalidate
96
+ Content-Type:
97
+ - application/json; charset=utf-8
98
+ Date:
99
+ - Mon, 22 Apr 2013 16:03:23 GMT
100
+ Etag:
101
+ - "\"713d90a679b7296644271208d96d7d8f\""
102
+ Server:
103
+ - nginx/1.2.2
104
+ Set-Cookie:
105
+ - <COOKIE-KEY>
106
+ Status:
107
+ - 200 OK
108
+ X-Runtime:
109
+ - "0.060774"
110
+ X-Ua-Compatible:
111
+ - IE=Edge,chrome=1
112
+ Content-Length:
113
+ - "40"
114
+ Connection:
115
+ - keep-alive
116
+ body:
156
117
  encoding: ASCII-8BIT
157
- string: !binary |-
158
- eyJ1cGRhdGVkQXQiOiIyMDEyLTEwLTA5VDIxOjQ1OjMyLjU5N1oifQ==
118
+ string: "{\"updatedAt\":\"2013-04-22T16:03:23.498Z\"}"
159
119
  http_version:
160
- recorded_at: Tue, 09 Oct 2012 21:45:32 GMT
161
- recorded_with: VCR 2.0.1
120
+ recorded_at: Mon, 22 Apr 2013 16:03:23 GMT
121
+ recorded_with: VCR 2.4.0
@@ -5,7 +5,7 @@ http_interactions:
5
5
  uri: https://api.parse.com/1/users
6
6
  body:
7
7
  encoding: UTF-8
8
- string: "{\"username\":\"0.40493766445323776\",\"password\":\"topsecret\"}"
8
+ string: "{\"username\":\"0.27216148534966633\",\"password\":\"topsecret\"}"
9
9
  headers:
10
10
  Content-Type:
11
11
  - application/json
@@ -16,9 +16,9 @@ http_interactions:
16
16
  X-Parse-Master-Key:
17
17
  - ""
18
18
  X-Parse-Rest-Api-Key:
19
- - jYdptjS76YHikuIFfJEgHD8UMIjH6cp2rWz4fo2C
19
+ - <X-Parse-REST-API-Key>
20
20
  X-Parse-Application-Id:
21
- - hnJRtntbYPvWfjqcqLZsdFaOKT0F3SfNU7Kc7woN
21
+ - <X-Parse-Application-Id>
22
22
  X-Parse-Session-Token:
23
23
  - ""
24
24
  Expect:
@@ -37,17 +37,17 @@ http_interactions:
37
37
  Content-Type:
38
38
  - application/json; charset=utf-8
39
39
  Date:
40
- - Thu, 10 Jan 2013 17:13:29 GMT
40
+ - Mon, 22 Apr 2013 16:03:27 GMT
41
41
  Location:
42
- - https://api.parse.com/1/users/TjN5LVdT83
42
+ - https://api.parse.com/1/users/j0rFtnWhJy
43
43
  Server:
44
44
  - nginx/1.2.2
45
45
  Set-Cookie:
46
- - _parse_session=BAh7BkkiD3Nlc3Npb25faWQGOgZFRiIlNDhiYjExOGE4MzY1ZmEzNGVjN2NmYjUxMzk2YjFjNzk%3D--242cb8875ea6f8b5c353b05bf1b9dcc351e5197e; domain=.parse.com; path=/; expires=Tue, 10-Jan-2023 17:13:29 GMT; secure; HttpOnly
46
+ - <COOKIE-KEY>
47
47
  Status:
48
48
  - 201 Created
49
49
  X-Runtime:
50
- - "0.312384"
50
+ - "0.346105"
51
51
  X-Ua-Compatible:
52
52
  - IE=Edge,chrome=1
53
53
  Content-Length:
@@ -56,7 +56,7 @@ http_interactions:
56
56
  - keep-alive
57
57
  body:
58
58
  encoding: ASCII-8BIT
59
- string: "{\"createdAt\":\"2013-01-10T17:13:29.400Z\",\"objectId\":\"TjN5LVdT83\",\"sessionToken\":\"ltj1s0ms3rft92u1avdnys7vn\"}"
59
+ string: "{\"createdAt\":\"2013-04-22T16:03:27.061Z\",\"objectId\":\"j0rFtnWhJy\",\"sessionToken\":\"rmranzh72f4mb3bptat7siph1\"}"
60
60
  http_version:
61
- recorded_at: Thu, 10 Jan 2013 17:13:29 GMT
62
- recorded_with: VCR 2.0.1
61
+ recorded_at: Mon, 22 Apr 2013 16:03:27 GMT
62
+ recorded_with: VCR 2.4.0
@@ -2,6 +2,8 @@ require 'parse/protocol'
2
2
  require 'parse/error'
3
3
  require 'parse/util'
4
4
 
5
+ require 'logger'
6
+
5
7
  require 'iron_mq'
6
8
 
7
9
  module Parse
@@ -17,6 +19,7 @@ module Parse
17
19
  attr_accessor :session_token
18
20
  attr_accessor :session
19
21
  attr_accessor :max_retries
22
+ attr_accessor :logger
20
23
 
21
24
  def initialize(data = {})
22
25
  @host = data[:host] || Protocol::HOST
@@ -25,6 +28,8 @@ module Parse
25
28
  @master_key = data[:master_key]
26
29
  @session_token = data[:session_token]
27
30
  @max_retries = data[:max_retries] || 3
31
+ @logger = data[:logger] || Logger.new(STDERR).tap{|l| l.level = Logger::INFO}
32
+
28
33
  @session = Patron::Session.new
29
34
  @session.timeout = 30
30
35
  @session.connect_timeout = 30
@@ -78,10 +83,10 @@ module Parse
78
83
 
79
84
  if @queue
80
85
 
81
- #while true
86
+ #while true
82
87
  # if @queue.reload.size >= @max_concurrent_requests
83
88
  # sleep 1
84
- # else
89
+ # else
85
90
  # add to queue before request
86
91
  @queue.post("1")
87
92
  response = @session.request(method, uri, {}, options)
@@ -97,7 +102,8 @@ module Parse
97
102
  parsed = JSON.parse(response.body)
98
103
 
99
104
  if response.status >= 400
100
- raise ParseProtocolError.new(parsed)
105
+ parsed ||= {}
106
+ raise ParseProtocolError.new({"error" => "HTTP Status #{response.status} Body #{response.body}"}.merge(parsed))
101
107
  end
102
108
 
103
109
  if content_type
@@ -105,11 +111,31 @@ module Parse
105
111
  end
106
112
 
107
113
  return parsed
108
- rescue Patron::TimeoutError
109
- retry if num_tries <= max_retries
114
+ rescue JSON::ParserError => e
115
+ if num_tries <= max_retries && response.status >= 500
116
+ log_retry(e, uri, query, body, response)
117
+ retry
118
+ end
119
+ raise
120
+ rescue Patron::TimeoutError => e
121
+ if num_tries <= max_retries
122
+ log_retry(e, uri, query, body, response)
123
+ retry
124
+ end
110
125
  raise
111
126
  rescue ParseProtocolError => e
112
- retry if e.code == Protocol::ERROR_TIMEOUT && num_tries <= max_retries
127
+ if num_tries <= max_retries
128
+ if e.code
129
+ sleep 60 if e.code == Protocol::ERROR_EXCEEDED_BURST_LIMIT
130
+ if [Protocol::ERROR_INTERNAL, Protocol::ERROR_TIMEOUT, Protocol::ERROR_EXCEEDED_BURST_LIMIT].include?(e.code)
131
+ log_retry(e, uri, query, body, response)
132
+ retry
133
+ end
134
+ elsif response.status >= 500
135
+ log_retry(e, uri, query, body, response)
136
+ retry
137
+ end
138
+ end
113
139
  raise
114
140
  end
115
141
  end
@@ -130,6 +156,11 @@ module Parse
130
156
  request(uri, :delete)
131
157
  end
132
158
 
159
+ protected
160
+
161
+ def log_retry(e, uri, query, body, response)
162
+ logger.warn{"Retrying Parse Error #{e.inspect} on request #{uri} #{CGI.unescape(query.inspect)} #{body.inspect} response #{response.inspect}"}
163
+ end
133
164
  end
134
165
 
135
166
 
@@ -185,6 +216,12 @@ module Parse
185
216
  def Parse.get(class_name, object_id = nil)
186
217
  data = Parse.client.get( Protocol.class_uri(class_name, object_id) )
187
218
  Parse.parse_json class_name, data
219
+ rescue ParseProtocolError => e
220
+ if e.code == Protocol::ERROR_OBJECT_NOT_FOUND_FOR_GET
221
+ e.message += ": #{class_name}:#{object_id}"
222
+ end
223
+
224
+ raise
188
225
  end
189
226
 
190
227
  end
@@ -10,6 +10,13 @@ module Parse
10
10
  attr_accessor :class_name
11
11
  alias :id :parse_object_id
12
12
 
13
+ def self.make(class_name, object_id)
14
+ Pointer.new(
15
+ Protocol::KEY_CLASS_NAME => class_name,
16
+ Protocol::KEY_OBJECT_ID => object_id
17
+ )
18
+ end
19
+
13
20
  def initialize(data)
14
21
  @class_name = data[Protocol::KEY_CLASS_NAME]
15
22
  @parse_object_id = data[Protocol::KEY_OBJECT_ID]
@@ -21,15 +28,17 @@ module Parse
21
28
  end
22
29
 
23
30
  def eql?(other)
24
- self.class.equal?(other.class) &&
25
- class_name == other.class_name &&
26
- parse_object_id == other.parse_object_id
31
+ Parse.object_pointer_equality?(self, other)
27
32
  end
28
33
 
29
34
  alias == eql?
30
35
 
31
36
  def hash
32
- class_name.hash ^ parse_object_id.hash
37
+ Parse.object_pointer_hash(self)
38
+ end
39
+
40
+ def new?
41
+ false
33
42
  end
34
43
 
35
44
  def as_json(*a)
@@ -193,37 +202,6 @@ module Parse
193
202
  end
194
203
  end
195
204
 
196
- class Decrement
197
- # '{"score": {"__op": "Decrement", "amount": 1 } }'
198
- attr_accessor :amount
199
-
200
- def initialize(amount)
201
- @amount = amount
202
- end
203
-
204
- def eql?(other)
205
- self.class.equal?(other.class) &&
206
- amount == other.amount
207
- end
208
-
209
- alias == eql?
210
-
211
- def hash
212
- amount.hash
213
- end
214
-
215
- def as_json(*a)
216
- {
217
- Protocol::KEY_OP => Protocol::KEY_DECREMENT,
218
- Protocol::KEY_AMOUNT => @amount
219
- }
220
- end
221
-
222
- def to_json(*a)
223
- as_json.to_json(*a)
224
- end
225
- end
226
-
227
205
  class ArrayOp
228
206
  # '{"myArray": {"__op": "Add", "objects": ["something", "something else"] } }'
229
207
  attr_accessor :operation
@@ -319,6 +297,7 @@ module Parse
319
297
  def initialize(data)
320
298
  data = Hash[data.map{ |k, v| [k.to_s, v] }] # convert hash keys to strings
321
299
  @local_filename = data["local_filename"] if data["local_filename"]
300
+ @parse_filename = data["name"] if data["name"]
322
301
  @parse_filename = data["parse_filename"] if data["parse_filename"]
323
302
  @content_type = data["content_type"] if data["content_type"]
324
303
  @url = data["url"] if data["url"]