parse-ruby-client 0.1.1 → 0.1.2

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.
data/Gemfile CHANGED
@@ -7,10 +7,12 @@ source "http://rubygems.org"
7
7
  # Include everything needed to run rake, tests, features, etc.
8
8
  group :development do
9
9
  gem "shoulda", ">= 0"
10
+ gem "test-unit", '= 2.5.0'
11
+ gem "mocha", '= 0.12.0', :require => false
10
12
  gem "bundler", "~> 1.0.0"
11
13
  gem "jeweler", "~> 1.6.4"
12
14
  gem "rcov", ">= 0"
13
15
  end
14
16
 
15
17
  gem "patron"
16
- gem "vcr"
18
+ gem "vcr"
@@ -6,10 +6,14 @@ GEM
6
6
  bundler (~> 1.0)
7
7
  git (>= 1.2.5)
8
8
  rake
9
+ metaclass (0.0.1)
10
+ mocha (0.12.0)
11
+ metaclass (~> 0.0.1)
9
12
  patron (0.4.17)
10
13
  rake (0.9.2.2)
11
14
  rcov (0.9.11)
12
15
  shoulda (2.11.3)
16
+ test-unit (2.5.0)
13
17
  vcr (2.0.1)
14
18
 
15
19
  PLATFORMS
@@ -18,7 +22,9 @@ PLATFORMS
18
22
  DEPENDENCIES
19
23
  bundler (~> 1.0.0)
20
24
  jeweler (~> 1.6.4)
25
+ mocha (= 0.12.0)
21
26
  patron
22
27
  rcov
23
28
  shoulda
29
+ test-unit (= 2.5.0)
24
30
  vcr
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.1.2
@@ -11,12 +11,16 @@ module Parse
11
11
  attr_accessor :host
12
12
  attr_accessor :application_id
13
13
  attr_accessor :api_key
14
+ attr_accessor :master_key
15
+ attr_accessor :session_token
14
16
  attr_accessor :session
15
17
 
16
18
  def initialize(data = {})
17
19
  @host = data[:host] || Protocol::HOST
18
20
  @application_id = data[:application_id]
19
21
  @api_key = data[:api_key]
22
+ @master_key = data[:master_key]
23
+ @session_token = data[:session_token]
20
24
  @session = Patron::Session.new
21
25
  @session.timeout = 30
22
26
  @session.connect_timeout = 30
@@ -25,8 +29,6 @@ module Parse
25
29
  @session.headers["Content-Type"] = "application/json"
26
30
  @session.headers["Accept"] = "application/json"
27
31
  @session.headers["User-Agent"] = "Parse for Ruby, 0.0"
28
- @session.headers[Protocol::HEADER_API_KEY] = @api_key
29
- @session.headers[Protocol::HEADER_APP_ID] = @application_id
30
32
  end
31
33
 
32
34
  # Perform an HTTP request for the given uri and method
@@ -34,6 +36,11 @@ module Parse
34
36
  # ParseProtocolError if the response has an error status code,
35
37
  # and will return the parsed JSON body on success, if there is one.
36
38
  def request(uri, method = :get, body = nil, query = nil, max_retries = 2)
39
+ @session.headers[Protocol::HEADER_MASTER_KEY] = @master_key
40
+ @session.headers[Protocol::HEADER_API_KEY] = @api_key
41
+ @session.headers[Protocol::HEADER_APP_ID] = @application_id
42
+ @session.headers[Protocol::HEADER_SESSION_TOKEN] = @session_token
43
+
37
44
  options = {}
38
45
  if body
39
46
  options[:data] = body
@@ -48,7 +55,7 @@ module Parse
48
55
  rescue Patron::TimeoutError
49
56
  num_tries += 1
50
57
  if num_tries <= max_retries
51
- retry
58
+ retry
52
59
  else
53
60
  raise Patron::TimeoutError
54
61
  end
@@ -92,10 +99,17 @@ module Parse
92
99
  # Initialize the singleton instance of Client which is used
93
100
  # by all API methods. Parse.init must be called before saving
94
101
  # or retrieving any objects.
95
- def Parse.init(data = {:application_id => ENV["PARSE_APPLICATION_ID"], :api_key => ENV["PARSE_REST_API_KEY"]})
96
- @@client = Client.new(data)
102
+ def Parse.init(data = {})
103
+ defaulted = {:application_id => ENV["PARSE_APPLICATION_ID"],
104
+ :api_key => ENV["PARSE_REST_API_KEY"]}
105
+ defaulted.merge!(data)
106
+
107
+ # use less permissive key if both are specified
108
+ defaulted[:master_key] = ENV["PARSE_MASTER_API_KEY"] unless data[:master_key] || defaulted[:api_key]
109
+
110
+ @@client = Client.new(defaulted)
97
111
  end
98
-
112
+
99
113
  # Used mostly for testing. Lets you delete the api key global vars.
100
114
  def Parse.destroy
101
115
  @@client = nil
@@ -14,6 +14,18 @@ module Parse
14
14
  @parse_object_id = data[Protocol::KEY_OBJECT_ID]
15
15
  end
16
16
 
17
+ def eql?(other)
18
+ self.class.equal?(other.class) &&
19
+ class_name == other.class_name &&
20
+ parse_object_id == other.parse_object_id
21
+ end
22
+
23
+ alias == eql?
24
+
25
+ def hash
26
+ class_name.hash ^ parse_object_id.hash
27
+ end
28
+
17
29
  def as_json(*a)
18
30
  {
19
31
  Protocol::KEY_TYPE => Protocol::TYPE_POINTER,
@@ -21,14 +33,14 @@ module Parse
21
33
  Protocol::KEY_OBJECT_ID => @parse_object_id
22
34
  }
23
35
  end
24
-
36
+
25
37
  def to_json(*a)
26
38
  as_json.to_json(*a)
27
39
  end
28
40
 
29
41
  # Retrieve the Parse object referenced by this pointer.
30
42
  def get
31
- Parse.get @class_name, @parse_object_id
43
+ Parse.get @class_name, @parse_object_id if @parse_object_id
32
44
  end
33
45
  end
34
46
 
@@ -48,13 +60,44 @@ module Parse
48
60
  end
49
61
  end
50
62
 
63
+ def eql?(other)
64
+ self.class.equal?(other.class) &&
65
+ value == other.value
66
+ end
67
+
68
+ alias == eql?
69
+
70
+ def hash
71
+ value.hash
72
+ end
73
+
74
+ def <=>(other)
75
+ value <=> other.value
76
+ end
77
+
78
+ def to_s
79
+ value.to_s
80
+ end
81
+
82
+ def method_missing(method, *args, &block)
83
+ if value.respond_to?(method)
84
+ value.send(method, *args, &block)
85
+ else
86
+ super(method)
87
+ end
88
+ end
89
+
90
+ def respond_to?(method, include_private = false)
91
+ super || value.respond_to?(method, include_private)
92
+ end
93
+
51
94
  def as_json(*a)
52
95
  {
53
96
  Protocol::KEY_TYPE => Protocol::TYPE_DATE,
54
97
  "iso" => value.iso8601
55
98
  }
56
99
  end
57
-
100
+
58
101
  def to_json(*a)
59
102
  as_json.to_json(*a)
60
103
  end
@@ -71,78 +114,139 @@ module Parse
71
114
  @value = Base64.decode64(bytes)
72
115
  end
73
116
 
117
+ def eql?(other)
118
+ self.class.equal?(other.class) &&
119
+ value == other.value
120
+ end
121
+
122
+ alias == eql?
123
+
124
+ def hash
125
+ value.hash
126
+ end
127
+
128
+ def <=>(other)
129
+ value <=> other.value
130
+ end
131
+
132
+ def method_missing(method, *args, &block)
133
+ if value.respond_to?(method)
134
+ value.send(method, *args, &block)
135
+ else
136
+ super(method)
137
+ end
138
+ end
139
+
140
+ def respond_to?(method, include_private = false)
141
+ super || value.respond_to?(method, include_private)
142
+ end
143
+
74
144
  def as_json(*a)
75
145
  {
76
146
  Protocol::KEY_TYPE => Protocol::TYPE_BYTES,
77
147
  "base64" => Base64.encode64(@value)
78
148
  }
79
149
  end
80
-
150
+
81
151
  def to_json(*a)
82
152
  as_json.to_json(*a)
83
153
  end
84
154
  end
85
-
155
+
86
156
  # Increment and Decrement
87
157
  # ------------------------------------------------------------
88
-
158
+
89
159
  class Increment
90
160
  # '{"score": {"__op": "Increment", "amount": 1 } }'
91
161
  attr_accessor :amount
92
-
162
+
93
163
  def initialize(amount)
94
164
  @amount = amount
95
165
  end
96
-
166
+
167
+ def eql?(other)
168
+ self.class.equal?(other.class) &&
169
+ amount == other.amount
170
+ end
171
+
172
+ alias == eql?
173
+
174
+ def hash
175
+ amount.hash
176
+ end
177
+
97
178
  def as_json(*a)
98
179
  {
99
180
  Protocol::KEY_OP => Protocol::KEY_INCREMENT,
100
181
  Protocol::KEY_AMOUNT => @amount
101
182
  }
102
183
  end
103
-
184
+
104
185
  def to_json(*a)
105
186
  as_json.to_json(*a)
106
187
  end
107
188
  end
108
-
189
+
109
190
  class Decrement
110
191
  # '{"score": {"__op": "Decrement", "amount": 1 } }'
111
192
  attr_accessor :amount
112
-
193
+
113
194
  def initialize(amount)
114
195
  @amount = amount
115
196
  end
116
-
197
+
198
+ def eql?(other)
199
+ self.class.equal?(other.class) &&
200
+ amount == other.amount
201
+ end
202
+
203
+ alias == eql?
204
+
205
+ def hash
206
+ amount.hash
207
+ end
208
+
117
209
  def as_json(*a)
118
210
  {
119
211
  Protocol::KEY_OP => Protocol::KEY_DECREMENT,
120
212
  Protocol::KEY_AMOUNT => @amount
121
213
  }
122
214
  end
123
-
215
+
124
216
  def to_json(*a)
125
217
  as_json.to_json(*a)
126
218
  end
127
219
  end
128
-
220
+
129
221
  # GeoPoint
130
222
  # ------------------------------------------------------------
131
-
223
+
132
224
  class GeoPoint
133
225
  # '{"location": {"__type":"GeoPoint", "latitude":40.0, "longitude":-30.0}}'
134
226
  attr_accessor :longitude, :latitude
135
-
227
+
136
228
  def initialize(data)
137
229
  @longitude = data["longitude"]
138
230
  @latitude = data["latitude"]
139
-
231
+
140
232
  if !@longitude && !@latitude
141
233
  @longitude = data[:longitude]
142
234
  @latitude = data[:latitude]
143
235
  end
144
236
  end
145
-
237
+
238
+ def eql?(other)
239
+ self.class.equal?(other.class) &&
240
+ longitude == other.longitude &&
241
+ latitude == other.latitude
242
+ end
243
+
244
+ alias == eql?
245
+
246
+ def hash
247
+ longitude.hash ^ latitude.hash
248
+ end
249
+
146
250
  def as_json(*a)
147
251
  {
148
252
  Protocol::KEY_TYPE => Protocol::TYPE_GEOPOINT,
@@ -150,11 +254,48 @@ module Parse
150
254
  "longitude" => @longitude
151
255
  }
152
256
  end
153
-
257
+
154
258
  def to_json(*a)
155
259
  as_json.to_json(*a)
156
260
  end
157
261
  end
158
-
262
+
263
+ # File
264
+ # ------------------------------------------------------------
265
+
266
+ class File
267
+ # '{"avatar": {"__type":"File", "name":"profile.png", "url"=>"http://files.parse.com/blah/profile.png"}}'
268
+ attr_accessor :name
269
+ attr_accessor :url
270
+
271
+ def initialize(data)
272
+ @name = data["name"]
273
+ @url = data["url"]
274
+ end
275
+
276
+ def eql?(other)
277
+ self.class.equal?(other.class) &&
278
+ url == other.url
279
+ end
280
+
281
+ alias == eql?
282
+
283
+ def hash
284
+ url.hash
285
+ end
286
+
287
+ def as_json(*a)
288
+ {
289
+ Protocol::KEY_TYPE => Protocol::TYPE_FILE,
290
+ "name" => @name,
291
+ "url" => @url
292
+ }
293
+ end
294
+
295
+ def to_json(*a)
296
+ as_json.to_json(*a)
297
+ end
298
+ end
299
+
159
300
 
160
301
  end
@@ -24,7 +24,7 @@ module Parse
24
24
  end
25
25
 
26
26
  def pointer
27
- Parse::Pointer.new self.merge(Parse::Protocol::KEY_CLASS_NAME => class_name)
27
+ Parse::Pointer.new(self.merge(Parse::Protocol::KEY_CLASS_NAME => class_name)) unless new?
28
28
  end
29
29
 
30
30
  # Merge a hash parsed from the JSON representation into
@@ -72,8 +72,17 @@ module Parse
72
72
 
73
73
  without_reserved = self.dup
74
74
  Protocol::RESERVED_KEYS.each { |k| without_reserved.delete(k) }
75
- body = without_reserved.to_json
76
75
 
76
+ without_relations = without_reserved
77
+ without_relations.each { |k,v|
78
+ if v.is_a? Hash
79
+ if v[Protocol::KEY_TYPE] == Protocol::TYPE_RELATION
80
+ without_relations.delete(k)
81
+ end
82
+ end
83
+ }
84
+
85
+ body = without_relations.to_json
77
86
  data = Parse.client.request(self.uri, method, body)
78
87
 
79
88
  if data
@@ -93,7 +102,7 @@ module Parse
93
102
  # values from the API.
94
103
  def refresh
95
104
  if @parse_object_id
96
- data = Parse.client.get self.uri
105
+ data = Parse.get @class_name, @parse_object_id
97
106
  if data
98
107
  parse data
99
108
  end
@@ -22,6 +22,13 @@ module Parse
22
22
  # Parse API.
23
23
  HEADER_API_KEY = "X-Parse-REST-API-Key"
24
24
 
25
+ # The HTTP header used for passing your API Master key to the
26
+ # Parse API.
27
+ HEADER_MASTER_KEY = "X-Parse-Master-Key"
28
+
29
+ # The HTTP header used for passing your authenticated session
30
+ HEADER_SESSION_TOKEN = "X-Parse-Session-Token"
31
+
25
32
  # JSON Keys
26
33
  # ----------------------------------------
27
34
 
@@ -90,11 +97,18 @@ module Parse
90
97
  # a file.
91
98
  TYPE_FILE = "File"
92
99
 
100
+ # The data type name for special JSON objects representing
101
+ # a Relation.
102
+ TYPE_RELATION = "Relation"
103
+
93
104
  # The class name for User objects, when referenced by a Pointer.
94
105
  CLASS_USER = "_User"
106
+
107
+ CLASS_INSTALLATION = "_Installation"
108
+
95
109
  USER_LOGIN_URI = "/#{VERSION}/login"
96
110
  PASSWORD_RESET_URI = "/#{VERSION}/requestPasswordReset"
97
-
111
+
98
112
  KEY_USER_SESSION_TOKEN = "sessionToken"
99
113
 
100
114
  # URI Helpers
@@ -109,7 +123,7 @@ module Parse
109
123
  "/#{VERSION}/classes/#{class_name}"
110
124
  end
111
125
  end
112
-
126
+
113
127
 
114
128
  # Construct a uri referencing a given Parse user
115
129
  # instance or the users category.
@@ -5,6 +5,7 @@ module Parse
5
5
  class Push
6
6
  attr_accessor :channels
7
7
  attr_accessor :channel
8
+ attr_accessor :where
8
9
  attr_accessor :type
9
10
  attr_accessor :expiration_time_interval
10
11
  attr_accessor :expiration_time
@@ -17,18 +18,22 @@ module Parse
17
18
 
18
19
  def save
19
20
  uri = Protocol.push_uri
20
-
21
+
21
22
  body = { :data => @data, :channel => @channel }
22
-
23
+
23
24
  if @channels
24
25
  body.merge!({ :channels => @channels })
25
26
  body.delete :channel
26
27
  end
27
-
28
+
29
+ if @where
30
+ body.merge!({ :where => @where })
31
+ end
32
+
28
33
  body.merge!({ :expiration_time_interval => @expiration_time_interval }) if @expiration_time_interval
29
- body.merge!({ :expiration_time => @expiration_time }) if @expiration_time
34
+ body.merge!({ :expiration_time => @expiration_time }) if @expiration_time
30
35
  body.merge!({ :type => @type }) if @type
31
-
36
+
32
37
  response = Parse.client.request uri, :post, body.to_json, nil
33
38
  end
34
39
 
@@ -15,9 +15,11 @@ module Parse
15
15
  @class_name = cls_name
16
16
  @where = {}
17
17
  @order = :ascending
18
+ @ors = []
18
19
  end
19
20
 
20
21
  def add_constraint(field, constraint)
22
+ raise ArgumentError, "cannot add constraint to an $or query" if @ors.size > 0
21
23
  current = where[field]
22
24
  if current && current.is_a?(Hash) && constraint.is_a?(Hash)
23
25
  current.merge! constraint
@@ -27,6 +29,12 @@ module Parse
27
29
  end
28
30
  #private :add_constraint
29
31
 
32
+ def or(query)
33
+ raise ArgumentError, "you must pass an entire #{self.class} to \#or" unless query.is_a?(self.class)
34
+ @ors << query
35
+ self
36
+ end
37
+
30
38
  def eq(field, value)
31
39
  add_constraint field, value
32
40
  self
@@ -67,16 +75,34 @@ module Parse
67
75
  self
68
76
  end
69
77
 
78
+ def in_query(field, query)
79
+ query_hash = {Parse::Protocol::KEY_CLASS_NAME => query.class_name, "where" => query.where}
80
+ add_constraint(field, "$inQuery" => query_hash)
81
+ end
82
+
70
83
  def count
71
84
  @count = true
72
85
  self
73
86
  end
74
87
 
88
+ def where_as_json
89
+ if @ors.size > 0
90
+ {"$or" => [self.where] + @ors.map{|query| query.where_as_json}}
91
+ else
92
+ @where
93
+ end
94
+ end
95
+
75
96
  def get
76
97
  uri = Protocol.class_uri @class_name
77
- query = { "where" => CGI.escape(@where.to_json) }
98
+ if @class_name == Parse::Protocol::CLASS_USER
99
+ uri = Protocol.user_uri
100
+ end
101
+
102
+
103
+ query = { "where" => CGI.escape(where_as_json.to_json) }
78
104
  set_order(query)
79
- [:count, :limit].each {|a| merge_attribute(a, query)}
105
+ [:count, :limit, :skip].each {|a| merge_attribute(a, query)}
80
106
 
81
107
  response = Parse.client.request uri, :get, nil, query
82
108
  Parse.parse_json class_name, response
@@ -9,9 +9,6 @@ module Parse
9
9
 
10
10
  if obj.nil?
11
11
  nil
12
- # String
13
- elsif obj.is_a? String
14
- parse_json class_name, JSON.parse(obj)
15
12
 
16
13
  # Array
17
14
  elsif obj.is_a? Array
@@ -25,10 +22,11 @@ module Parse
25
22
  parse_datatype obj
26
23
  elsif obj.size == 1 && obj.has_key?(Protocol::KEY_RESULTS) && obj[Protocol::KEY_RESULTS].is_a?(Array)
27
24
  obj[Protocol::KEY_RESULTS].collect { |o| parse_json(class_name, o) }
28
- else # otherwise it must be a regular object
29
- Parse::Object.new class_name, obj
25
+ else # otherwise it must be a regular object, so deep parse it avoiding re-JSON.parsing raw Strings
26
+ Parse::Object.new class_name, Hash[obj.map{|k,v| [k, parse_json(nil, v)]}]
30
27
  end
31
28
 
29
+ # primitive
32
30
  else
33
31
  obj
34
32
  end
@@ -44,6 +42,10 @@ module Parse
44
42
  Parse::Bytes.new obj
45
43
  when Protocol::TYPE_DATE
46
44
  Parse::Date.new obj
45
+ when Protocol::TYPE_GEOPOINT
46
+ Parse::GeoPoint.new obj
47
+ when Protocol::TYPE_FILE
48
+ Parse::File.new obj
47
49
  end
48
50
  end
49
51
  end
@@ -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.1"
8
+ s.version = "0.1.2"
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 = "2012-07-04"
12
+ s.date = "2012-08-31"
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 = [
@@ -52,7 +52,7 @@ Gem::Specification.new do |s|
52
52
  s.homepage = "http://github.com/adelevie/parse-ruby-client"
53
53
  s.licenses = ["MIT"]
54
54
  s.require_paths = ["lib"]
55
- s.rubygems_version = "1.8.10"
55
+ s.rubygems_version = "1.8.24"
56
56
  s.summary = "A simple Ruby client for the parse.com REST API"
57
57
 
58
58
  if s.respond_to? :specification_version then
@@ -62,6 +62,8 @@ Gem::Specification.new do |s|
62
62
  s.add_runtime_dependency(%q<patron>, [">= 0"])
63
63
  s.add_runtime_dependency(%q<vcr>, [">= 0"])
64
64
  s.add_development_dependency(%q<shoulda>, [">= 0"])
65
+ s.add_development_dependency(%q<test-unit>, ["= 2.5.0"])
66
+ s.add_development_dependency(%q<mocha>, ["= 0.12.0"])
65
67
  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
66
68
  s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
67
69
  s.add_development_dependency(%q<rcov>, [">= 0"])
@@ -69,6 +71,8 @@ Gem::Specification.new do |s|
69
71
  s.add_dependency(%q<patron>, [">= 0"])
70
72
  s.add_dependency(%q<vcr>, [">= 0"])
71
73
  s.add_dependency(%q<shoulda>, [">= 0"])
74
+ s.add_dependency(%q<test-unit>, ["= 2.5.0"])
75
+ s.add_dependency(%q<mocha>, ["= 0.12.0"])
72
76
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
73
77
  s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
74
78
  s.add_dependency(%q<rcov>, [">= 0"])
@@ -77,6 +81,8 @@ Gem::Specification.new do |s|
77
81
  s.add_dependency(%q<patron>, [">= 0"])
78
82
  s.add_dependency(%q<vcr>, [">= 0"])
79
83
  s.add_dependency(%q<shoulda>, [">= 0"])
84
+ s.add_dependency(%q<test-unit>, ["= 2.5.0"])
85
+ s.add_dependency(%q<mocha>, ["= 0.12.0"])
80
86
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
81
87
  s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
82
88
  s.add_dependency(%q<rcov>, [">= 0"])
@@ -9,6 +9,7 @@ rescue Bundler::BundlerError => e
9
9
  end
10
10
  require 'test/unit'
11
11
  require 'shoulda'
12
+ require 'mocha'
12
13
 
13
14
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
15
  $LOAD_PATH.unshift(File.dirname(__FILE__))
@@ -7,19 +7,21 @@ class TestDatatypes < Test::Unit::TestCase
7
7
  Parse::Protocol::KEY_OBJECT_ID => "12345abcd"
8
8
  }
9
9
  p = Parse::Pointer.new data
10
-
11
- assert_equal p.to_json, "{\"__type\":\"Pointer\",\"#{Parse::Protocol::KEY_CLASS_NAME}\":\"DatatypeTestClass\",\"#{Parse::Protocol::KEY_OBJECT_ID}\":\"12345abcd\"}"
10
+
11
+ assert_equal p.to_json, "{\"__type\":\"Pointer\",\"#{Parse::Protocol::KEY_CLASS_NAME}\":\"DatatypeTestClass\",\"#{Parse::Protocol::KEY_OBJECT_ID}\":\"12345abcd\"}"
12
12
  end
13
-
13
+
14
14
  def test_date
15
15
  date_time = DateTime.now
16
16
  data = date_time
17
17
  parse_date = Parse::Date.new data
18
-
18
+
19
19
  assert_equal parse_date.value, date_time
20
20
  assert_equal JSON.parse(parse_date.to_json)["iso"], date_time.iso8601
21
+ assert_equal 0, parse_date <=> parse_date
22
+ assert_equal 0, Parse::Date.new(data) <=> Parse::Date.new(data)
21
23
  end
22
-
24
+
23
25
  def test_bytes
24
26
  data = {
25
27
  "base64" => Base64.encode64("testing bytes!")
@@ -30,21 +32,21 @@ class TestDatatypes < Test::Unit::TestCase
30
32
  assert_equal JSON.parse(byte.to_json)[Parse::Protocol::KEY_TYPE], Parse::Protocol::TYPE_BYTES
31
33
  assert_equal JSON.parse(byte.to_json)["base64"], Base64.encode64("testing bytes!")
32
34
  end
33
-
35
+
34
36
  def test_increment
35
37
  amount = 5
36
38
  increment = Parse::Increment.new amount
37
-
39
+
38
40
  assert_equal increment.to_json, "{\"__op\":\"Increment\",\"amount\":#{amount}}"
39
41
  end
40
-
42
+
41
43
  def test_decrement
42
44
  amount = 5
43
45
  increment = Parse::Decrement.new amount
44
-
46
+
45
47
  assert_equal increment.to_json, "{\"__op\":\"Decrement\",\"amount\":#{amount}}"
46
48
  end
47
-
49
+
48
50
  def test_geopoint
49
51
  # '{"location": {"__type":"GeoPoint", "latitude":40.0, "longitude":-30.0}}'
50
52
  data = {
@@ -52,9 +54,28 @@ class TestDatatypes < Test::Unit::TestCase
52
54
  "latitude" => -30.0
53
55
  }
54
56
  gp = Parse::GeoPoint.new data
55
-
56
- assert_equal JSON.parse(gp.to_json)["longitude"], data["longitude"]
57
+
58
+ assert_equal JSON.parse(gp.to_json)["longitude"], data["longitude"]
57
59
  assert_equal JSON.parse(gp.to_json)["latitude"], data["latitude"]
58
60
  assert_equal JSON.parse(gp.to_json)[Parse::Protocol::KEY_TYPE], Parse::Protocol::TYPE_GEOPOINT
61
+
62
+ post = Parse::Object.new("Post")
63
+ post["location"] = gp
64
+ post.save
65
+ q = Parse.get("Post", post.id)
66
+ assert_equal gp, q["location"]
67
+ end
68
+
69
+ def test_file
70
+ data = {"name" => "blah.png"}
71
+ file = Parse::File.new(data)
72
+ assert_equal JSON.parse(file.to_json)["name"], data["name"]
73
+ assert_equal JSON.parse(file.to_json)[Parse::Protocol::KEY_TYPE], Parse::Protocol::TYPE_FILE
74
+
75
+ post = Parse::Object.new("Post")
76
+ post["avatar"] = file
77
+ post.save
78
+ q = Parse.get("Post", post.id)
79
+ assert_equal file.name, q["avatar"].name
59
80
  end
60
81
  end
@@ -22,8 +22,7 @@ class TestObject < Test::Unit::TestCase
22
22
 
23
23
  def test_pointer
24
24
  post = Parse::Object.new "Post"
25
- pointer = post.pointer
26
- assert_equal pointer.class_name, post.class_name
25
+ assert_nil post.pointer
27
26
 
28
27
  post.save
29
28
  pointer = post.pointer
@@ -64,4 +63,16 @@ class TestObject < Test::Unit::TestCase
64
63
  end
65
64
  end
66
65
 
66
+ def test_deep_parse
67
+ other = Parse::Object.new "Post"
68
+ other.save
69
+ post = Parse::Object.new "Post"
70
+ post["other"] = other.pointer
71
+ post.save
72
+
73
+ q = Parse.get("Post", post.id)
74
+ assert_equal Parse::Pointer, q["other"].class
75
+ assert_equal other.pointer, q["other"]
76
+ end
77
+
67
78
  end
@@ -1,14 +1,32 @@
1
1
  require 'helper'
2
2
 
3
3
  class TestPush < Test::Unit::TestCase
4
-
4
+
5
5
  def setup
6
6
  Parse.init
7
7
  end
8
8
 
9
- def test_send
10
- # gotta mock
9
+ def test_save
10
+ data = {:foo => 'bar',
11
+ :alert => 'message'}
12
+ pf_push = Parse::Push.new(data, "some_chan")
13
+ pf_push.type = 'ios'
14
+
15
+ query = Parse::Query.new(Parse::Protocol::CLASS_INSTALLATION).eq('deviceToken', 'baz')
16
+ pf_push.where = query.where
17
+
18
+ Parse::Client.any_instance.expects(:request).with do |uri, method, body, query|
19
+ hash = JSON.parse(body)
20
+ assert_equal :post, method
21
+ assert has_entries('type' => 'ios', 'channel' => "some_chan").matches?([hash])
22
+ assert has_entries('foo' => 'bar', 'alert' => 'message').matches?([hash['data']])
23
+ assert has_entries('deviceToken' => 'baz').matches?([hash['where']])
24
+ assert_nil query
25
+ true
26
+ end.returns({}.to_json)
27
+
28
+ pf_push.save
11
29
  end
12
-
30
+
13
31
 
14
32
  end
@@ -27,7 +27,7 @@ class TestQuery < Test::Unit::TestCase
27
27
  q.add_constraint("player", { "$regex" => "regex voodoo"})
28
28
  assert_equal q.where["player"], { "$regex" => "regex voodoo"}
29
29
  end
30
-
30
+
31
31
  def test_eq
32
32
  q = Parse::Query.new "TestQuery"
33
33
  q.eq("points", 5)
@@ -35,4 +35,46 @@ class TestQuery < Test::Unit::TestCase
35
35
  q.eq("player", "michael@jordan.com")
36
36
  assert_equal q.where, {"points" => 5, "player" => "michael@jordan.com"}
37
37
  end
38
+
39
+ def test_limit_skip
40
+ q = Parse::Query.new "TestQuery"
41
+ q.limit = 2
42
+ q.skip = 3
43
+ query_matcher = has_entries(:limit => 2, :skip => 3)
44
+ Parse::Client.any_instance.expects(:request).with(anything, :get, nil, query_matcher).returns({}.to_json)
45
+ q.get
46
+ end
47
+
48
+ def test_count
49
+ q = Parse::Query.new "TestQuery"
50
+ q.count = true
51
+ query_matcher = has_entries(:count => true)
52
+ Parse::Client.any_instance.expects(:request).with(anything, :get, nil, query_matcher).returns({}.to_json)
53
+ q.get
54
+ end
55
+
56
+ def test_or
57
+ foo = Parse::Object.new "Post"
58
+ foo["random"] = rand
59
+ foo.save
60
+ foo_query = Parse::Query.new("Post").eq("random", foo["random"])
61
+ assert_equal 1, foo_query.get.size
62
+
63
+ bar = Parse::Object.new "Post"
64
+ bar["random"] = rand
65
+ bar.save
66
+ bar_query = Parse::Query.new("Post").eq("random", bar["random"])
67
+ assert_equal 1, foo_query.get.size
68
+
69
+ query = foo_query.or(bar_query)
70
+ assert_equal 2, query.get.size
71
+ end
72
+
73
+ def test_in_query
74
+ outer_query = Parse::Query.new "Outer"
75
+ inner_query = Parse::Query.new "Inner"
76
+ inner_query.eq("foo", "bar")
77
+ outer_query.in_query("inner", inner_query)
78
+ assert_equal({"inner"=>{"$inQuery"=>{"className"=>"Inner", "where"=>{"foo"=>"bar"}}}}, outer_query.where)
79
+ end
38
80
  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.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-07-04 00:00:00.000000000Z
13
+ date: 2012-08-31 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: patron
17
- requirement: &70246977048500 !ruby/object:Gem::Requirement
17
+ requirement: !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,15 @@ dependencies:
22
22
  version: '0'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *70246977048500
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
26
31
  - !ruby/object:Gem::Dependency
27
32
  name: vcr
28
- requirement: &70246977027920 !ruby/object:Gem::Requirement
33
+ requirement: !ruby/object:Gem::Requirement
29
34
  none: false
30
35
  requirements:
31
36
  - - ! '>='
@@ -33,21 +38,63 @@ dependencies:
33
38
  version: '0'
34
39
  type: :runtime
35
40
  prerelease: false
36
- version_requirements: *70246977027920
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
37
47
  - !ruby/object:Gem::Dependency
38
48
  name: shoulda
39
- requirement: &70246977025900 !ruby/object:Gem::Requirement
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
40
58
  none: false
41
59
  requirements:
42
60
  - - ! '>='
43
61
  - !ruby/object:Gem::Version
44
62
  version: '0'
63
+ - !ruby/object:Gem::Dependency
64
+ name: test-unit
65
+ requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - '='
69
+ - !ruby/object:Gem::Version
70
+ version: 2.5.0
71
+ type: :development
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - '='
77
+ - !ruby/object:Gem::Version
78
+ version: 2.5.0
79
+ - !ruby/object:Gem::Dependency
80
+ name: mocha
81
+ requirement: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - '='
85
+ - !ruby/object:Gem::Version
86
+ version: 0.12.0
45
87
  type: :development
46
88
  prerelease: false
47
- version_requirements: *70246977025900
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - '='
93
+ - !ruby/object:Gem::Version
94
+ version: 0.12.0
48
95
  - !ruby/object:Gem::Dependency
49
96
  name: bundler
50
- requirement: &70246977023480 !ruby/object:Gem::Requirement
97
+ requirement: !ruby/object:Gem::Requirement
51
98
  none: false
52
99
  requirements:
53
100
  - - ~>
@@ -55,10 +102,15 @@ dependencies:
55
102
  version: 1.0.0
56
103
  type: :development
57
104
  prerelease: false
58
- version_requirements: *70246977023480
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: 1.0.0
59
111
  - !ruby/object:Gem::Dependency
60
112
  name: jeweler
61
- requirement: &70246977022580 !ruby/object:Gem::Requirement
113
+ requirement: !ruby/object:Gem::Requirement
62
114
  none: false
63
115
  requirements:
64
116
  - - ~>
@@ -66,10 +118,15 @@ dependencies:
66
118
  version: 1.6.4
67
119
  type: :development
68
120
  prerelease: false
69
- version_requirements: *70246977022580
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ~>
125
+ - !ruby/object:Gem::Version
126
+ version: 1.6.4
70
127
  - !ruby/object:Gem::Dependency
71
128
  name: rcov
72
- requirement: &70246977020640 !ruby/object:Gem::Requirement
129
+ requirement: !ruby/object:Gem::Requirement
73
130
  none: false
74
131
  requirements:
75
132
  - - ! '>='
@@ -77,7 +134,12 @@ dependencies:
77
134
  version: '0'
78
135
  type: :development
79
136
  prerelease: false
80
- version_requirements: *70246977020640
137
+ version_requirements: !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ! '>='
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
81
143
  description: A simple Ruby client for the parse.com REST API
82
144
  email: adelevie@gmail.com
83
145
  executables: []
@@ -132,7 +194,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
132
194
  version: '0'
133
195
  segments:
134
196
  - 0
135
- hash: -2755924312958518124
197
+ hash: 2354067513295992545
136
198
  required_rubygems_version: !ruby/object:Gem::Requirement
137
199
  none: false
138
200
  requirements:
@@ -141,7 +203,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
141
203
  version: '0'
142
204
  requirements: []
143
205
  rubyforge_project:
144
- rubygems_version: 1.8.10
206
+ rubygems_version: 1.8.24
145
207
  signing_key:
146
208
  specification_version: 3
147
209
  summary: A simple Ruby client for the parse.com REST API