parse-ruby-client 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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