parse-ruby-client 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +15 -0
  2. data/.travis.yml +2 -1
  3. data/Gemfile +4 -6
  4. data/Gemfile.lock +18 -18
  5. data/README.md +1 -1
  6. data/Rakefile +1 -1
  7. data/VERSION +1 -1
  8. data/example.rb +2 -1
  9. data/fixtures/vcr_cassettes/test_batch_update_nils_delete_keys.yml +57 -0
  10. data/fixtures/vcr_cassettes/test_empty_response.yml +72 -0
  11. data/fixtures/vcr_cassettes/test_get_missing.yml +95 -38
  12. data/fixtures/vcr_cassettes/test_image_file_associate_with_object.yml +2089 -0
  13. data/fixtures/vcr_cassettes/test_image_file_save.yml +1928 -0
  14. data/fixtures/vcr_cassettes/test_object_id.yml +56 -0
  15. data/fixtures/vcr_cassettes/test_reset_password.yml +109 -0
  16. data/fixtures/vcr_cassettes/test_retries.yml +357 -0
  17. data/fixtures/vcr_cassettes/test_retries_404.yml +72 -0
  18. data/fixtures/vcr_cassettes/test_retries_404_correct.yml +72 -0
  19. data/fixtures/vcr_cassettes/test_retries_json_error.yml +357 -0
  20. data/fixtures/vcr_cassettes/test_retries_server_error.yml +357 -0
  21. data/fixtures/vcr_cassettes/test_server_update.yml +248 -191
  22. data/fixtures/vcr_cassettes/test_user_login.yml +276 -0
  23. data/fixtures/vcr_cassettes/test_xget.yml +280 -0
  24. data/lib/faraday/better_retry.rb +94 -0
  25. data/lib/faraday/extended_parse_json.rb +39 -0
  26. data/lib/faraday/get_method_override.rb +32 -0
  27. data/lib/parse-ruby-client.rb +9 -9
  28. data/lib/parse/batch.rb +2 -3
  29. data/lib/parse/client.rb +72 -161
  30. data/lib/parse/cloud.rb +2 -1
  31. data/lib/parse/datatypes.rb +6 -1
  32. data/lib/parse/error.rb +7 -3
  33. data/lib/parse/installation.rb +18 -0
  34. data/lib/parse/model.rb +2 -1
  35. data/lib/parse/object.rb +7 -1
  36. data/lib/parse/protocol.rb +10 -0
  37. data/lib/parse/push.rb +3 -0
  38. data/lib/parse/query.rb +5 -2
  39. data/lib/parse/user.rb +1 -0
  40. data/lib/parse/util.rb +2 -0
  41. data/parse-ruby-client.gemspec +35 -15
  42. data/test/helper.rb +55 -1
  43. data/test/middleware/better_retry_test.rb +57 -0
  44. data/test/middleware/extend_parse_json_test.rb +55 -0
  45. data/test/test_client.rb +78 -28
  46. data/test/test_datatypes.rb +14 -0
  47. data/test/test_object.rb +16 -0
  48. metadata +39 -34
  49. data/lib/parse/http_client.rb +0 -84
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Parse
2
3
  module Cloud
3
4
 
@@ -20,4 +21,4 @@ module Parse
20
21
  end
21
22
 
22
23
  end
23
- end
24
+ end
@@ -1,3 +1,6 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'time'
3
+ require 'date'
1
4
  require 'base64'
2
5
 
3
6
  module Parse
@@ -71,12 +74,14 @@ module Parse
71
74
  attr_accessor :value
72
75
 
73
76
  def initialize(data)
74
- if data.is_a? DateTime
77
+ if data.respond_to?(:iso8601)
75
78
  @value = data
76
79
  elsif data.is_a? Hash
77
80
  @value = DateTime.parse data["iso"]
78
81
  elsif data.is_a? String
79
82
  @value = DateTime.parse data
83
+ else
84
+ raise "data doesn't act like time #{data.inspect}"
80
85
  end
81
86
  end
82
87
 
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Parse
2
3
 
3
4
  # Base exception class for errors thrown by the Parse
@@ -17,8 +18,8 @@ module Parse
17
18
  def initialize(response)
18
19
  @response = response
19
20
  if response
20
- @code = response["code"]
21
- @error = response["error"]
21
+ @code = response["code"]
22
+ @error = response["error"]
22
23
  end
23
24
 
24
25
  super("#{@code}: #{@error}")
@@ -33,4 +34,7 @@ module Parse
33
34
  end
34
35
  end
35
36
 
36
- end
37
+ class ParseProtocolRetry < ParseProtocolError
38
+ end
39
+
40
+ end
@@ -0,0 +1,18 @@
1
+ require 'parse/protocol'
2
+ require 'parse/client'
3
+ require 'parse/error'
4
+ require 'parse/object'
5
+
6
+ module Parse
7
+ class Installation < Parse::Object
8
+
9
+ def initialize(data = nil)
10
+ super(Parse::Protocol::CLASS_INSTALLATION, data)
11
+ end
12
+
13
+ def uri
14
+ Protocol.installation_uri @parse_object_id
15
+ end
16
+
17
+ end
18
+ end
@@ -1,7 +1,8 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Parse
2
3
  class Model < Parse::Object
3
4
  def initialize
4
5
  super(self.class.to_s)
5
6
  end
6
7
  end
7
- end
8
+ end
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  require 'parse/protocol'
2
3
  require 'parse/client'
3
4
  require 'parse/error'
@@ -95,9 +96,14 @@ module Parse
95
96
  self.merge(Parse::Protocol::KEY_CLASS_NAME => class_name)
96
97
  end
97
98
 
99
+ # Handle the addition of Array#to_h in Ruby 2.1
100
+ def should_call_to_h?(value)
101
+ value.respond_to?(:to_h) && !value.kind_of?(Array)
102
+ end
103
+
98
104
  def to_h(*a)
99
105
  Hash[rest_api_hash.map do |key, value|
100
- [key, value.respond_to?(:to_h) ? value.to_h : value]
106
+ [key, should_call_to_h?(value) ? value.to_h : value]
101
107
  end]
102
108
  end
103
109
  alias :as_json :to_h
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Parse
2
3
  # A module which encapsulates the specifics of Parse's REST API.
3
4
  module Protocol
@@ -141,6 +142,15 @@ module Parse
141
142
  end
142
143
  end
143
144
 
145
+ # Construct a uri referencing a given Parse installation
146
+ # class or instance (of object_id is non-nil).
147
+ def Protocol.installation_uri(object_id = nil)
148
+ if object_id
149
+ "/#{VERSION}/installations/#{object_id}"
150
+ else
151
+ "/#{VERSION}/installations"
152
+ end
153
+ end
144
154
 
145
155
  # Construct a uri referencing a given Parse user
146
156
  # instance or the users category.
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  require 'cgi'
2
3
  require 'parse/error'
3
4
 
@@ -9,6 +10,7 @@ module Parse
9
10
  attr_accessor :type
10
11
  attr_accessor :expiration_time_interval
11
12
  attr_accessor :expiration_time
13
+ attr_accessor :push_time
12
14
  attr_accessor :data
13
15
 
14
16
  def initialize(data, channel = "")
@@ -33,6 +35,7 @@ module Parse
33
35
 
34
36
  body.merge!({ :expiration_interval => @expiration_time_interval }) if @expiration_time_interval
35
37
  body.merge!({ :expiration_time => @expiration_time }) if @expiration_time
38
+ body.merge!({ :push_time => @push_time }) if @push_time
36
39
  body.merge!({ :type => @type }) if @type
37
40
 
38
41
  response = Parse.client.request uri, :post, body.to_json, nil
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  require 'cgi'
2
3
 
3
4
  module Parse
@@ -119,11 +120,13 @@ module Parse
119
120
  uri = Protocol.class_uri @class_name
120
121
  if @class_name == Parse::Protocol::CLASS_USER
121
122
  uri = Protocol.user_uri
123
+ elsif @class_name == Parse::Protocol::CLASS_INSTALLATION
124
+ uri = Protocol.installation_uri
122
125
  end
123
- query = { "where" => CGI.escape(where_as_json.to_json) }
126
+ query = { "where" => where_as_json.to_json }
124
127
  set_order(query)
125
128
  [:count, :limit, :skip, :include].each {|a| merge_attribute(a, query)}
126
- Parse.client.logger.info{"Parse query for #{uri} #{CGI.unescape(query.inspect)}"}
129
+ Parse.client.logger.info{"Parse query for #{uri} #{query.inspect}"}
127
130
  response = Parse.client.request uri, :get, nil, query
128
131
 
129
132
  if response.is_a?(Hash) && response.has_key?(Protocol::KEY_RESULTS) && response[Protocol::KEY_RESULTS].is_a?(Array)
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  require 'parse/protocol'
2
3
  require 'parse/client'
3
4
  require 'parse/error'
@@ -1,3 +1,5 @@
1
+ # -*- encoding : utf-8 -*-
2
+
1
3
  module Parse
2
4
 
3
5
  # Parse a JSON representation into a fully instantiated
@@ -2,14 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
+ # stub: parse-ruby-client 0.3.0 ruby lib
5
6
 
6
7
  Gem::Specification.new do |s|
7
8
  s.name = "parse-ruby-client"
8
- s.version = "0.2.0"
9
+ s.version = "0.3.0"
9
10
 
10
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
11
13
  s.authors = ["Alan deLevie", "Adam Alpern"]
12
- s.date = "2013-10-08"
14
+ s.date = "2014-07-31"
13
15
  s.description = "A simple Ruby client for the parse.com REST API"
14
16
  s.email = "adelevie@gmail.com"
15
17
  s.extra_rdoc_files = [
@@ -40,16 +42,26 @@ Gem::Specification.new do |s|
40
42
  "fixtures/vcr_cassettes/test_decrement.yml",
41
43
  "fixtures/vcr_cassettes/test_deep_parse.yml",
42
44
  "fixtures/vcr_cassettes/test_destroy.yml",
45
+ "fixtures/vcr_cassettes/test_empty_response.yml",
43
46
  "fixtures/vcr_cassettes/test_eq_pointerize.yml",
44
47
  "fixtures/vcr_cassettes/test_equality.yml",
45
48
  "fixtures/vcr_cassettes/test_get.yml",
46
49
  "fixtures/vcr_cassettes/test_get_missing.yml",
50
+ "fixtures/vcr_cassettes/test_image_file_associate_with_object.yml",
51
+ "fixtures/vcr_cassettes/test_image_file_save.yml",
47
52
  "fixtures/vcr_cassettes/test_include.yml",
48
53
  "fixtures/vcr_cassettes/test_new_model.yml",
49
54
  "fixtures/vcr_cassettes/test_new_object.yml",
50
55
  "fixtures/vcr_cassettes/test_nils_delete_keys.yml",
56
+ "fixtures/vcr_cassettes/test_object_id.yml",
51
57
  "fixtures/vcr_cassettes/test_parse_delete.yml",
52
58
  "fixtures/vcr_cassettes/test_pointer.yml",
59
+ "fixtures/vcr_cassettes/test_reset_password.yml",
60
+ "fixtures/vcr_cassettes/test_retries.yml",
61
+ "fixtures/vcr_cassettes/test_retries_404.yml",
62
+ "fixtures/vcr_cassettes/test_retries_404_correct.yml",
63
+ "fixtures/vcr_cassettes/test_retries_json_error.yml",
64
+ "fixtures/vcr_cassettes/test_retries_server_error.yml",
53
65
  "fixtures/vcr_cassettes/test_save_with_sub_objects.yml",
54
66
  "fixtures/vcr_cassettes/test_saving_boolean_values.yml",
55
67
  "fixtures/vcr_cassettes/test_saving_nested_objects.yml",
@@ -58,15 +70,19 @@ Gem::Specification.new do |s|
58
70
  "fixtures/vcr_cassettes/test_text_file_save.yml",
59
71
  "fixtures/vcr_cassettes/test_update.yml",
60
72
  "fixtures/vcr_cassettes/test_updated_at.yml",
73
+ "fixtures/vcr_cassettes/test_user_login.yml",
61
74
  "fixtures/vcr_cassettes/test_user_save.yml",
62
75
  "fixtures/vcr_cassettes/test_xget.yml",
76
+ "lib/faraday/better_retry.rb",
77
+ "lib/faraday/extended_parse_json.rb",
78
+ "lib/faraday/get_method_override.rb",
63
79
  "lib/parse-ruby-client.rb",
64
80
  "lib/parse/batch.rb",
65
81
  "lib/parse/client.rb",
66
82
  "lib/parse/cloud.rb",
67
83
  "lib/parse/datatypes.rb",
68
84
  "lib/parse/error.rb",
69
- "lib/parse/http_client.rb",
85
+ "lib/parse/installation.rb",
70
86
  "lib/parse/model.rb",
71
87
  "lib/parse/object.rb",
72
88
  "lib/parse/protocol.rb",
@@ -78,6 +94,8 @@ Gem::Specification.new do |s|
78
94
  "test/cloud_functions/MyCloudCode/cloud/main.js",
79
95
  "test/config/global.json",
80
96
  "test/helper.rb",
97
+ "test/middleware/better_retry_test.rb",
98
+ "test/middleware/extend_parse_json_test.rb",
81
99
  "test/parsers.jpg",
82
100
  "test/test_batch.rb",
83
101
  "test/test_client.rb",
@@ -95,47 +113,49 @@ Gem::Specification.new do |s|
95
113
  ]
96
114
  s.homepage = "http://github.com/adelevie/parse-ruby-client"
97
115
  s.licenses = ["MIT"]
98
- s.require_paths = ["lib"]
99
- s.rubygems_version = "1.8.24"
116
+ s.rubygems_version = "2.2.2"
100
117
  s.summary = "A simple Ruby client for the parse.com REST API"
101
118
 
102
119
  if s.respond_to? :specification_version then
103
- s.specification_version = 3
120
+ s.specification_version = 4
104
121
 
105
122
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
106
- s.add_runtime_dependency(%q<patron>, [">= 0"])
107
- s.add_runtime_dependency(%q<iron_mq>, [">= 0"])
123
+ s.add_runtime_dependency(%q<faraday>, [">= 0"])
124
+ s.add_runtime_dependency(%q<faraday_middleware>, [">= 0"])
108
125
  s.add_development_dependency(%q<bundler>, [">= 0"])
109
126
  s.add_development_dependency(%q<shoulda>, [">= 0"])
110
127
  s.add_development_dependency(%q<test-unit>, ["= 2.5.0"])
111
128
  s.add_development_dependency(%q<mocha>, ["= 0.12.0"])
112
129
  s.add_development_dependency(%q<jeweler>, ["~> 1.8.5"])
113
130
  s.add_development_dependency(%q<simplecov>, [">= 0"])
114
- s.add_development_dependency(%q<webmock>, [">= 0"])
131
+ s.add_development_dependency(%q<webmock>, ["~> 1.9.0"])
115
132
  s.add_development_dependency(%q<vcr>, [">= 0"])
133
+ s.add_development_dependency(%q<pry>, [">= 0"])
116
134
  else
117
- s.add_dependency(%q<patron>, [">= 0"])
118
- s.add_dependency(%q<iron_mq>, [">= 0"])
135
+ s.add_dependency(%q<faraday>, [">= 0"])
136
+ s.add_dependency(%q<faraday_middleware>, [">= 0"])
119
137
  s.add_dependency(%q<bundler>, [">= 0"])
120
138
  s.add_dependency(%q<shoulda>, [">= 0"])
121
139
  s.add_dependency(%q<test-unit>, ["= 2.5.0"])
122
140
  s.add_dependency(%q<mocha>, ["= 0.12.0"])
123
141
  s.add_dependency(%q<jeweler>, ["~> 1.8.5"])
124
142
  s.add_dependency(%q<simplecov>, [">= 0"])
125
- s.add_dependency(%q<webmock>, [">= 0"])
143
+ s.add_dependency(%q<webmock>, ["~> 1.9.0"])
126
144
  s.add_dependency(%q<vcr>, [">= 0"])
145
+ s.add_dependency(%q<pry>, [">= 0"])
127
146
  end
128
147
  else
129
- s.add_dependency(%q<patron>, [">= 0"])
130
- s.add_dependency(%q<iron_mq>, [">= 0"])
148
+ s.add_dependency(%q<faraday>, [">= 0"])
149
+ s.add_dependency(%q<faraday_middleware>, [">= 0"])
131
150
  s.add_dependency(%q<bundler>, [">= 0"])
132
151
  s.add_dependency(%q<shoulda>, [">= 0"])
133
152
  s.add_dependency(%q<test-unit>, ["= 2.5.0"])
134
153
  s.add_dependency(%q<mocha>, ["= 0.12.0"])
135
154
  s.add_dependency(%q<jeweler>, ["~> 1.8.5"])
136
155
  s.add_dependency(%q<simplecov>, [">= 0"])
137
- s.add_dependency(%q<webmock>, [">= 0"])
156
+ s.add_dependency(%q<webmock>, ["~> 1.9.0"])
138
157
  s.add_dependency(%q<vcr>, [">= 0"])
158
+ s.add_dependency(%q<pry>, [">= 0"])
139
159
  end
140
160
  end
141
161
 
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  require 'rubygems'
2
3
  require 'bundler'
3
4
  begin
@@ -52,4 +53,57 @@ class ParseTestCase < Test::Unit::TestCase
52
53
  def setup
53
54
  @client = Parse.init(:logger => Logger.new(STDERR).tap{|l| l.level = Logger::ERROR})
54
55
  end
55
- end
56
+ end
57
+
58
+ module Faraday
59
+ module LiveServerConfig
60
+ def live_server=(value)
61
+ @@live_server = case value
62
+ when /^http/
63
+ URI(value)
64
+ when /./
65
+ URI('http://127.0.0.1:4567')
66
+ end
67
+ end
68
+
69
+ def live_server?
70
+ defined? @@live_server
71
+ end
72
+
73
+ # Returns an object that responds to `host` and `port`.
74
+ def live_server
75
+ live_server? and @@live_server
76
+ end
77
+ end
78
+ class TestCase < Test::Unit::TestCase
79
+ extend LiveServerConfig
80
+ self.live_server = ENV['LIVE']
81
+
82
+ def test_default
83
+ assert true
84
+ end unless defined? ::MiniTest
85
+
86
+ def capture_warnings
87
+ old, $stderr = $stderr, StringIO.new
88
+ begin
89
+ yield
90
+ $stderr.string
91
+ ensure
92
+ $stderr = old
93
+ end
94
+ end
95
+
96
+ def self.jruby?
97
+ defined? RUBY_ENGINE and 'jruby' == RUBY_ENGINE
98
+ end
99
+
100
+ def self.rbx?
101
+ defined? RUBY_ENGINE and 'rbx' == RUBY_ENGINE
102
+ end
103
+
104
+ def self.ssl_mode?
105
+ ENV['SSL'] == 'yes'
106
+ end
107
+ end
108
+ end
109
+
@@ -0,0 +1,57 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'helper'
3
+
4
+ module Middleware
5
+ class BeterRetryTest < Faraday::TestCase
6
+ def setup
7
+ @times_called = 0
8
+ end
9
+
10
+ def conn(retry_options = {})
11
+ Faraday.new do |b|
12
+ b.use Faraday::BetterRetry, retry_options
13
+ b.adapter :test do |stub|
14
+ stub.post('/unstable') {
15
+ @times_called += 1
16
+ @explode.call @times_called
17
+ }
18
+ end
19
+ end
20
+ end
21
+
22
+ def test_unhandled_error
23
+ @explode = lambda {|n| raise "boom!" }
24
+ assert_raise(RuntimeError) { conn.post("/unstable") }
25
+ assert_equal 1, @times_called
26
+ end
27
+
28
+ def test_handled_error
29
+ @explode = lambda {|n| raise Errno::ETIMEDOUT }
30
+ assert_raise(Errno::ETIMEDOUT) { conn.post("/unstable") }
31
+ assert_equal 3, @times_called
32
+ end
33
+
34
+ def test_new_max_retries
35
+ @explode = lambda {|n| raise Errno::ETIMEDOUT }
36
+ assert_raise(Errno::ETIMEDOUT) { conn(:max => 3).post("/unstable") }
37
+ assert_equal 4, @times_called
38
+ end
39
+
40
+ def test_interval
41
+ @explode = lambda {|n| raise Errno::ETIMEDOUT }
42
+ started = Time.now
43
+ assert_raise(Errno::ETIMEDOUT) {
44
+ conn(:max => 2, :interval => 0.1).post("/unstable")
45
+ }
46
+ assert_in_delta 0.2, Time.now - started, 0.03
47
+ end
48
+
49
+ def test_custom_exceptions
50
+ @explode = lambda {|n| raise "boom!" }
51
+ assert_raise(RuntimeError) {
52
+ conn(:exceptions => StandardError).post("/unstable")
53
+ }
54
+ assert_equal 3, @times_called
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,55 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'helper'
3
+
4
+ module Middleware
5
+ class ExtedParseJsonTest < Faraday::TestCase
6
+
7
+ def conn(retry_options = {})
8
+ Faraday.new do |b|
9
+ b.use Faraday::ExtendedParseJson
10
+ b.adapter :test do |stub|
11
+ stub.get('/invalid_json') { [200, {}, 'something'] }
12
+ stub.get('/valid_json') { [200, {}, {'var' => 1}.to_json] }
13
+ stub.get('/parse_error_code') { [403, {}, {'code' => Parse::Protocol::ERROR_INTERNAL}.to_json] }
14
+ stub.get('/empty_response') { [403, {}, ''] }
15
+ stub.get('/404') { [404, {}, {}.to_json] }
16
+ stub.get('/500') { [500, {}, {'text' => 'Internal Server Error'}.to_json] }
17
+ end
18
+ end
19
+ end
20
+
21
+ def test_invalid_json
22
+ assert_raise(Faraday::Error::ParsingError) { conn.get("/invalid_json") }
23
+ end
24
+
25
+ def test_valid_json
26
+ resp = conn.get("/valid_json")
27
+ assert_equal 200, resp.status
28
+ assert_equal ({'var' => 1}), resp.body
29
+ end
30
+
31
+ def test_empty_response
32
+ ex = assert_raise(Parse::ParseProtocolError) { conn.get("/empty_response") }
33
+ assert_match /403/, ex.to_s
34
+ assert_equal "HTTP Status 403 Body ", ex.error
35
+ end
36
+
37
+ def test_parse_error_code
38
+ ex = assert_raise(Parse::ParseProtocolError) { conn.get("/parse_error_code") }
39
+ assert_match /403/, ex.to_s
40
+ assert_equal Parse::Protocol::ERROR_INTERNAL, ex.code
41
+ end
42
+
43
+ def test_404
44
+ ex = assert_raise(Parse::ParseProtocolError) { conn.get("/404") }
45
+ assert_match /404/, ex.to_s
46
+ end
47
+
48
+ def test_500
49
+ ex = assert_raise(Parse::ParseProtocolError) { conn.get("/500") }
50
+ assert_match /500/, ex.to_s
51
+ assert_match /Internal Server Error/, ex.to_s
52
+ end
53
+
54
+ end
55
+ end