rapidash 0.2.2 → 0.3.0.beta

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fc2547c5c59b614c4e483ade6e06387a5daa74fe
4
- data.tar.gz: be96076c18545377419376da043dfb689f319c3f
3
+ metadata.gz: 9c189f614b87a9f1d01e06b573191ab55cfc5304
4
+ data.tar.gz: 4e105da2de17bca6c15e66055e9cae54f9f2e502
5
5
  SHA512:
6
- metadata.gz: a440f140a6e093e5cdd6722251248609ac54400936d692ad9f152b83502413821ce534fb3ccbcc36d4d25138b90a35391060472cdf664ce3aab6df43b89ae299
7
- data.tar.gz: 851d7dbbc4f05207fa45c0f64c4db4b44a16f6aa0503bfbb410e2383caffc84ad7dc75639c24e93bfd8f6be5b19a5c230a5eb06622d92234515c0b81569bd31e
6
+ metadata.gz: cf3736b55a2373d1f29addff7e56904f3a7eed7c457797f984de95f7447a451e1f8d6f097e7e17125da7c0ac3dd9a65cab232090e24ac55c7b02f6290936fbb1
7
+ data.tar.gz: 2917f78dda7987f293c15d95cc760d901f597aec9d8a300552257f68720cf466d304a239b2dfadbbef07ebed9741c375985c273e5ba271ba8032c891c1d61ebe
data/.travis.yml CHANGED
@@ -4,3 +4,7 @@ rvm:
4
4
  - 1.9.2
5
5
  - 1.9.3
6
6
  - 2.0.0
7
+ - jruby-18mode
8
+ - jruby-19mode
9
+ - rbx-18mode
10
+ - rbx-19mode
@@ -0,0 +1,13 @@
1
+ require 'faraday'
2
+
3
+ module Faraday
4
+ class Response::RaiseRapidashError < Response::Middleware
5
+
6
+ def on_complete(env)
7
+ status = env[:status].to_i
8
+ klass = Rapidash.response_exception_class || Rapidash::ResponseError
9
+ raise klass.new(env) if (400..599).include?(status)
10
+ end
11
+
12
+ end
13
+ end
@@ -9,7 +9,7 @@ module Rapidash
9
9
  end
10
10
 
11
11
  class << self
12
- attr_accessor :patch, :raise_error
12
+ attr_accessor :patch, :raise_error, :extension, :encoder
13
13
 
14
14
  def method(method)
15
15
  case method
@@ -36,6 +36,32 @@ module Rapidash
36
36
  def raise_errors
37
37
  @raise_error = true
38
38
  end
39
+
40
+ # How should the request body for POST and PUT requests
41
+ # be formatted.
42
+ #
43
+ # Examples:
44
+ # class Client < Rapidash::Client
45
+ # encode_request_with :json
46
+ # end
47
+ #
48
+ # Arguments:
49
+ #
50
+ # format - Symbol. One of :url_encoded, :multipart, :json
51
+ #
52
+ # Returns String of set format
53
+ def encode_request_with(format)
54
+ format = format.to_s.to_sym
55
+
56
+ unless [:url_encoded, :multipart, :json].include?(format)
57
+ raise ArgumentError, 'you must pass one of :url_encoded, :multipart or :json to encode_request_with'
58
+ end
59
+
60
+ # Map json to multi_json to make it consistent with MutiJson parsing of responses
61
+ format = :multi_json if format == :json
62
+
63
+ @encoder ||= format
64
+ end
39
65
  end
40
66
 
41
67
  # Instance methods
@@ -79,5 +105,25 @@ module Rapidash
79
105
  def delete(url, options = {})
80
106
  request(:delete, url, options)
81
107
  end
108
+
109
+ private
110
+
111
+ def connection_builder
112
+ lambda do |builder|
113
+ builder.request self.class.encoder || :url_encoded
114
+
115
+ if self.class.respond_to?(:raise_error) && self.class.raise_error
116
+ builder.use Faraday::Response::RaiseRapidashError
117
+ end
118
+
119
+ builder.use FaradayMiddleware::FollowRedirects
120
+ builder.use FaradayMiddleware::Mashify
121
+
122
+ builder.use FaradayMiddleware::MultiJson::ParseJson, :content_type => /\bjson$/
123
+ builder.use FaradayMiddleware::ParseXml, :content_type => /\bxml$/
124
+
125
+ builder.adapter :net_http
126
+ end
127
+ end
82
128
  end
83
129
  end
@@ -1,4 +1,6 @@
1
1
  require 'faraday'
2
+ require 'faraday_middleware'
3
+ require 'faraday_middleware/multi_json'
2
4
 
3
5
  module Rapidash
4
6
  module HTTPClient
@@ -13,31 +15,21 @@ module Rapidash
13
15
 
14
16
  def connection
15
17
  raise ConfigurationError.new "Site is required" unless site
16
- @connection ||= Faraday.new(site)
18
+
19
+ @connection ||= Faraday.new(site) do |builder|
20
+ if login || password
21
+ builder.use Faraday::Request::BasicAuthentication, login, password
22
+ end
23
+
24
+ connection_builder.call(builder)
25
+ end
17
26
  end
18
27
 
19
28
  def request(verb, url, options = {})
20
29
  url = connection.build_url(normalize_url(url), options[:params]).to_s
21
- response = connection.run_request verb, url, options[:body], options[:header] do |request|
22
- request.headers.update(:Authorization => connection.basic_auth(login, password)) if login && password
23
- end
30
+ response = connection.run_request(verb, url, options[:body], options[:header])
24
31
 
25
- process_response(response, verb, options)
26
- end
27
-
28
- def process_response(response, verb, options)
29
- # "foo"[0] does not work in 1.8.7, "foo"[0,1] is required
30
- case response.status.to_s[0, 1]
31
- when "5", "4"
32
- error = ResponseError.new(response)
33
- raise error if self.class.respond_to?(:raise_error) && self.class.raise_error
34
- return nil
35
- #Handle redirects
36
- when "3"
37
- request(verb, response.headers["location"], options)
38
- when "2"
39
- return Response.new(response)
40
- end
32
+ response.body
41
33
  end
42
34
  end
43
35
  end
@@ -25,7 +25,7 @@ module Rapidash
25
25
  options[:raise_errors] = self.class.respond_to?(:raise_error) && self.class.raise_error
26
26
  response = oauth_access_token.send(verb.to_sym, "#{site}/#{url}", options)
27
27
 
28
- Response.new(response)
28
+ response.body
29
29
  end
30
30
 
31
31
  def access_token_from_code(code, url)
@@ -36,7 +36,7 @@ module Rapidash
36
36
  private
37
37
 
38
38
  def client
39
- @oauth_client ||= ::OAuth2::Client.new(uid, secret, :site => site)
39
+ @oauth_client ||= ::OAuth2::Client.new(uid, secret, :site => site, :connection_build => connection_builder)
40
40
  end
41
41
 
42
42
  def oauth_access_token
@@ -0,0 +1,74 @@
1
+ module Rapidash
2
+
3
+ # Rapidash::ResponseError
4
+ # Exception that gets raised if the response is an error (4xx or 5xx)
5
+ # Raised by Faraday::Response::RaiseRapidashError
6
+ # see lib/faraday/response/raise_rapidash_error.rb
7
+ #
8
+ # Formats a readable error message including HTTP status, method and requested URL
9
+ #
10
+ # Examples:
11
+ #
12
+ # client.posts.create!(title: '')
13
+ # Rapidash::ResponseError: 422 POST http://acme.com/api/v1/posts.json
14
+ #
15
+ # begin
16
+ # client.posts.create!(title: '')
17
+ # rescue Rapidash::ResponseError => response
18
+ # response.status # => 422
19
+ # response.method # => "POST"
20
+ # response.url # => "http://acme.com/api/v1/posts.json"
21
+ # response.body # => "{"errors":["title can't be blank", "body can't be blank"]}"
22
+ # end
23
+ #
24
+ # Hint: Can be easily sub-classed to provide a custom exception handler class
25
+ # with specific error formatting. Defining an `errors` method that returns a String or Array
26
+ # will include the errors in the exception message:
27
+ #
28
+ # class MyCustomResponseError < Rapidash::ResponseError
29
+ # def errors
30
+ # data = JSON.parse(body)
31
+ # data['errors']
32
+ # end
33
+ # end
34
+ #
35
+ # Rapidash.response_exception_class = MyCustomResponseError
36
+ #
37
+ # client.posts.create!(title: '')
38
+ # MyCustomResponseError: 422 POST http://acme.com/api/v1/posts.json | Errors: title can't be blank, body can't be blank
39
+ #
40
+ # begin
41
+ # client.posts.create!(title: '')
42
+ # rescue Rapidash::ResponseError => response
43
+ # response.status # => 422
44
+ # response.errors # => ["title can't be blank", "body can't be blank"]
45
+ # end
46
+ #
47
+ class ResponseError < StandardError
48
+ attr_reader :response, :body, :status, :method, :url
49
+
50
+ def initialize(response = nil)
51
+ @response = response
52
+
53
+ @body = response[:body]
54
+ @status = response[:status].to_i
55
+ @method = response[:method].to_s.upcase
56
+ @url = response[:url]
57
+
58
+ super(message)
59
+ end
60
+
61
+ private
62
+
63
+ def message
64
+ msg = "#{status} #{method} #{url}"
65
+
66
+ if respond_to?(:errors) && !(errors.blank?)
67
+ errors.map(&:to_s).join(', ') if errors.kind_of?(Array)
68
+ msg = "#{msg} | Errors: #{errors.to_s}"
69
+ end
70
+
71
+ msg
72
+ end
73
+ end
74
+ end
@@ -1,13 +1,62 @@
1
+ # Rapidash::TestClient
2
+ # A dummy client for testing with. Create a new test
3
+ # client by including this module and initializing
4
+ # with a set of responses.
5
+ # Example:
6
+ #
7
+ # class TesterClient
8
+ # include Rapidash::TestClient
9
+ # end
10
+ #
11
+ # responses = {
12
+ # get: { "foo" => "bar" },
13
+ # post: { "baz" => "data" }
14
+ # }
15
+ #
16
+ # client = TesterClient.new(responses)
17
+ #
18
+ # Example with JSON support:
19
+ #
20
+ # responses = {
21
+ # get: { "foo" => '{"some": 123, "json": 456}' }
22
+ # }
23
+ #
24
+ # client = TesterClient.new(responses, json: true)
1
25
  module Rapidash
2
26
  module TestClient
3
- attr_accessor :responses
27
+ attr_reader :responses, :stubs, :json
4
28
 
5
- def initialize(options = {})
6
- @responses = options.delete(:responses)
29
+ def initialize(responses, options = {})
30
+ @json = options[:json] || false
31
+ @responses = responses
32
+ build_stubs
7
33
  end
8
34
 
9
35
  def request(verb, url, options = {})
10
- Response.new(responses[verb][url])
36
+ connection.send(verb, url, options).body
37
+ end
38
+
39
+ private
40
+
41
+ def build_stubs
42
+ @stubs = Faraday::Adapter::Test::Stubs.new do |stub|
43
+ responses.each_pair do |verb, req|
44
+ req.each_pair do |url, body|
45
+ stub.send(verb, url) { [200, {}, body] }
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ def connection
52
+ @connection ||= Faraday.new do |builder|
53
+ builder.adapter :test, stubs
54
+ builder.use FaradayMiddleware::Mashify
55
+
56
+ if json
57
+ builder.use FaradayMiddleware::ParseJson
58
+ end
59
+ end
11
60
  end
12
61
  end
13
62
  end
@@ -1,3 +1,3 @@
1
1
  module Rapidash
2
- VERSION = "0.2.2"
2
+ VERSION = "0.3.0.beta"
3
3
  end
data/lib/rapidash.rb CHANGED
@@ -1,11 +1,12 @@
1
1
  #Required for pluralization and camelcasing
2
2
  require "active_support/core_ext/string"
3
+ require "active_support/core_ext/module/attribute_accessors"
4
+ require "json"
3
5
 
4
6
  require "rapidash/version"
5
7
 
6
- require "rapidash/errors"
7
-
8
- require "rapidash/response"
8
+ require "faraday/response/raise_rapidash_error"
9
+ require "rapidash/response_error"
9
10
 
10
11
  require "rapidash/resourceable"
11
12
  require "rapidash/client"
@@ -18,4 +19,7 @@ require "rapidash/oauth_client"
18
19
  require "rapidash/test_client"
19
20
 
20
21
  module Rapidash
22
+ mattr_accessor :response_exception_class
23
+
24
+ class ConfigurationError < StandardError; end
21
25
  end
data/rapidash.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
2
+ lib = File.expand_path("../lib", __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'rapidash/version'
4
+ require "rapidash/version"
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "rapidash"
@@ -22,11 +22,16 @@ Gem::Specification.new do |spec|
22
22
  spec.add_development_dependency "rake"
23
23
  spec.add_development_dependency "rspec", "~> 2.8"
24
24
  spec.add_development_dependency "simplecov", "~> 0.7"
25
+ spec.add_development_dependency "json"
25
26
 
26
- spec.add_dependency 'json'
27
- spec.add_dependency 'faraday', '~> 0.8'
27
+ spec.add_dependency "faraday", "~> 0.8"
28
+ spec.add_dependency "faraday_middleware", "~> 0.9"
29
+ spec.add_dependency "faraday_middleware-multi_json", "~> 0.0"
28
30
  spec.add_dependency "oauth2", "~>0.6"
29
31
  spec.add_dependency "hashie", "~>1.2"
30
- spec.add_dependency "activesupport", "~>3.0"
31
-
32
+ if RUBY_VERSION < "1.9.3"
33
+ spec.add_dependency "activesupport", "~> 3.0"
34
+ else
35
+ spec.add_dependency "activesupport", ">= 3.0.0"
36
+ end
32
37
  end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe Faraday::Response::RaiseRapidashError do
4
+ context "successful response" do
5
+ let(:env) { { :status => '200' } }
6
+
7
+ it "should not raise an exception" do
8
+ expect {
9
+ subject.on_complete(env)
10
+ }.to_not raise_exception(Rapidash::ResponseError)
11
+ end
12
+ end
13
+
14
+ context "error response" do
15
+ let(:env) { { :status => '404', :method => 'post', :url => 'http://acme.com/api/posts' } }
16
+
17
+ it "should raise an exception" do
18
+ expect {
19
+ subject.on_complete(env)
20
+ }.to raise_exception(Rapidash::ResponseError)
21
+ end
22
+
23
+ describe "custom reponse error" do
24
+ before :each do
25
+ class MyCustomResponseError < Rapidash::ResponseError; end
26
+ Rapidash.response_exception_class = MyCustomResponseError
27
+ end
28
+
29
+ it "should raise a custom excpetion class if specified" do
30
+ expect {
31
+ subject.on_complete(env)
32
+ }.to raise_exception(MyCustomResponseError)
33
+ end
34
+
35
+ after :each do
36
+ Rapidash.response_exception_class = nil
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,10 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
- class Client < Rapidash::Client
4
- method :test
5
- end
6
-
7
-
8
3
  class OAuthClientTester < Rapidash::Client
9
4
  method :oauth
10
5
  end
@@ -25,13 +20,13 @@ class HTTPClientErrorTester < HTTPClientTester
25
20
  raise_errors
26
21
  end
27
22
 
28
- class TestClientTester
23
+ class TestClientTester < Rapidash::Client
29
24
  method :test
30
25
  end
31
26
 
32
27
  describe Rapidash::Client do
33
28
 
34
- let!(:subject) { Client.new }
29
+ let(:test_client) { TestClientTester.new({}) }
35
30
 
36
31
  describe "#method" do
37
32
  it "should include the HTTPClient" do
@@ -45,8 +40,7 @@ describe Rapidash::Client do
45
40
  end
46
41
 
47
42
  it "should include the OAuthClient" do
48
- client = TestClientTester.new
49
- client.class.ancestors.should include(Rapidash::TestClient)
43
+ test_client.class.ancestors.should include(Rapidash::TestClient)
50
44
  end
51
45
 
52
46
  it "should raise an error on anything else" do
@@ -85,61 +79,75 @@ describe Rapidash::Client do
85
79
 
86
80
  describe ".site=" do
87
81
  it "should clear the connection variable after set new site" do
88
- subject.instance_variable_get(:@connection).should eql(nil)
89
- subject.site = "foo"
90
- subject.instance_variable_set(:@connection, "Not nil")
82
+ test_client.instance_variable_get(:@connection).should eql(nil)
83
+ test_client.site = "foo"
84
+ test_client.instance_variable_set(:@connection, "Not nil")
91
85
 
92
- subject.site = "bar"
93
- subject.instance_variable_get(:@connection).should eql(nil)
86
+ test_client.site = "bar"
87
+ test_client.instance_variable_get(:@connection).should eql(nil)
94
88
  end
95
89
 
96
90
  it "should set the site variable" do
97
- subject.instance_variable_get(:@site).should eql(nil)
98
- subject.site = "foo"
99
- subject.instance_variable_get(:@site).should eql("foo")
91
+ test_client.instance_variable_get(:@site).should eql(nil)
92
+ test_client.site = "foo"
93
+ test_client.instance_variable_get(:@site).should eql("foo")
100
94
  end
101
95
  end
102
96
 
97
+ describe ".encode_request_with" do
98
+ let(:klass) { test_client.class }
99
+
100
+ it "should set encoder for valid argument" do
101
+ klass.encode_request_with(:json)
102
+ expect(klass.encoder).to eq :json
103
+ end
104
+
105
+ it "should raise exception for invalid argument" do
106
+ expect {
107
+ klass.encode_request_with(:wibble)
108
+ }.to raise_exception(ArgumentError)
109
+ end
110
+ end
103
111
 
104
112
  describe ".get" do
105
113
  it "should call request" do
106
- subject.should_receive(:request).with(:get, "foo", {})
107
- subject.get("foo")
114
+ test_client.should_receive(:request).with(:get, "foo", {})
115
+ test_client.get("foo")
108
116
  end
109
117
  end
110
118
 
111
119
  describe ".post" do
112
120
  it "should call request" do
113
- subject.should_receive(:request).with(:post, "foo", {})
114
- subject.post("foo")
121
+ test_client.should_receive(:request).with(:post, "foo", {})
122
+ test_client.post("foo")
115
123
  end
116
124
  end
117
125
 
118
126
  describe ".put" do
119
127
  it "should call request" do
120
- subject.should_receive(:request).with(:put, "foo", {})
121
- subject.put("foo")
128
+ test_client.should_receive(:request).with(:put, "foo", {})
129
+ test_client.put("foo")
122
130
  end
123
131
  end
124
132
 
125
133
  describe ".patch" do
126
134
  it "should call request" do
127
- subject.should_receive(:request).with(:patch, "foo", {})
128
- subject.patch("foo")
135
+ test_client.should_receive(:request).with(:patch, "foo", {})
136
+ test_client.patch("foo")
129
137
  end
130
138
  end
131
139
 
132
140
  describe ".delete" do
133
141
  it "should call request" do
134
- subject.should_receive(:request).with(:delete, "foo", {})
135
- subject.delete("foo")
142
+ test_client.should_receive(:request).with(:delete, "foo", {})
143
+ test_client.delete("foo")
136
144
  end
137
145
  end
138
146
 
139
147
  describe ".normalize_url" do
140
148
  it "should use the instance extension if set" do
141
- subject.extension = :json
142
- subject.normalize_url("users").should eql("users.json")
149
+ test_client.extension = :json
150
+ test_client.normalize_url("users").should eql("users.json")
143
151
  end
144
152
 
145
153
  it "should use the class extension if set" do
@@ -147,7 +155,7 @@ describe Rapidash::Client do
147
155
  end
148
156
 
149
157
  it "should return the url if no extension if set" do
150
- subject.normalize_url("users").should eql("users")
158
+ test_client.normalize_url("users").should eql("users")
151
159
  end
152
160
  end
153
161
  end
@@ -46,64 +46,25 @@ describe Rapidash::HTTPClient do
46
46
  end
47
47
 
48
48
  describe "authorization" do
49
- let!(:options) { { :login => "login", :password => "password" } }
50
- let!(:subject) { HTTPTester.new(options) }
49
+ let!(:subject) { HTTPTester.new(:login => "login", :password => "password") }
51
50
 
52
- it "should authorize with login and password" do
53
- subject.should_receive(:process_response).with("response", :get, {})
54
- subject.connection.should_receive(:basic_auth).with(options[:login], options[:password])
55
- subject.connection.stub_chain('app.call').and_return("response")
56
- subject.request(:get, "foo")
51
+ it "should delegate to Faraday's basic auth" do
52
+ expect(subject.connection.builder.handlers).to include(Faraday::Request::BasicAuthentication)
57
53
  end
58
54
  end
59
55
 
60
- it "should call response" do
61
- subject.should_receive(:process_response).with("response", :get, {})
62
- subject.connection.should_receive(:run_request).with(:get, "http://example.com/foo", nil, nil).and_return("response")
63
- subject.request(:get, "foo")
64
- end
65
- end
66
-
67
- describe ".process_response" do
68
-
69
- let!(:valid_response) { OpenStruct.new(:status => "200")}
70
- let!(:redirect_response) { OpenStruct.new(:status => "301", :headers => {"location" => "http://example.com/redirect"})}
71
- let!(:error_response) { OpenStruct.new(:status => "404")}
72
-
73
- before(:each) do
74
- subject.site = "http://example.com"
75
- end
56
+ describe "without authorization" do
57
+ let!(:subject) { HTTPTester.new() }
76
58
 
77
- describe "valid response" do
78
- before(:each) do
79
- Rapidash::Response.should_receive(:new).and_return("response")
80
- end
81
-
82
- it "should return a response object" do
83
- response = subject.process_response(valid_response, :get, {})
84
- response.should eql("response")
85
- end
86
-
87
- it "should perform a redirect" do
88
- subject.should_receive(:request).with(:get, "http://example.com/redirect", anything).and_return(subject.process_response(valid_response, :get, {}))
89
- response = subject.process_response(redirect_response, :get, {})
90
- response.should eql("response")
59
+ it "should delegate to Faraday's basic auth" do
60
+ expect(subject.connection.builder.handlers).to_not include(Faraday::Request::BasicAuthentication)
91
61
  end
92
62
  end
93
63
 
94
- describe "error response" do
95
- it "should not raise an error by default" do
96
- response = subject.process_response(error_response, :get, {})
97
- response.should be_nil
98
- end
99
-
100
- it "should raise an error if the option is set" do
101
- subject = HTTPErrorTester.new
102
- expect {
103
- response = subject.process_response(error_response, :get, {})
104
- }.to raise_error(Rapidash::ResponseError)
105
- end
106
-
64
+ it "should call response" do
65
+ response = double(:body => "response")
66
+ subject.connection.should_receive(:run_request).with(:get, "http://example.com/foo", nil, nil).and_return(response)
67
+ subject.request(:get, "foo")
107
68
  end
108
69
  end
109
70
  end
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  module Integration
4
-
5
4
  class Repo < Rapidash::Base
6
5
  end
7
6
 
@@ -14,29 +13,17 @@ module Integration
14
13
  method :test
15
14
  resource :users
16
15
  end
17
-
18
16
  end
19
17
 
20
- gazler = OpenStruct.new({
21
- :headers => { "content-type" => "application/json" },
22
- :body => { :name => "Gary Rennie" }.to_json
23
- })
24
-
25
- repos = OpenStruct.new({
26
- :headers => { "content-type" => "application/json" },
27
- :body => [ { :name => "Githug" } ].to_json
28
- })
29
-
30
18
  responses = {
31
19
  :get => {
32
- "members/Gazler" => gazler,
33
- "members/Gazler/repos" => repos,
20
+ "members/Gazler" => { :name => "Gary Rennie" }.to_json,
21
+ "members/Gazler/repos" => [{ :name => "Githug" }].to_json,
34
22
  }
35
23
  }
36
24
 
37
25
  describe "An actual Rapidash Client" do
38
-
39
- let!(:client) { Integration::Client.new(:responses => responses) }
26
+ let(:client) { Integration::Client.new(responses, :json => true) }
40
27
 
41
28
  it "should get the user from the API" do
42
29
  client.users!("Gazler").name.should eql("Gary Rennie")
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- class OAuthTester
3
+ class OAuthTester < Rapidash::Client
4
4
  include Rapidash::OAuthClient
5
5
  end
6
6
 
@@ -11,11 +11,6 @@ class OAuthErrorTester < OAuthTester
11
11
  end
12
12
 
13
13
  describe Rapidash::OAuthClient do
14
-
15
- before(:each) do
16
- Rapidash::Response.stub(:new).and_return(Hashie::Mash.new)
17
- end
18
-
19
14
  let(:options) {
20
15
  {
21
16
  :uid => "foo",
@@ -67,45 +62,19 @@ describe Rapidash::OAuthClient do
67
62
  end
68
63
 
69
64
  describe ".request" do
70
-
71
- let(:request) { mock }
65
+ let(:request) { mock(:body => 'data') }
72
66
 
73
67
  describe "object returned from API call" do
74
-
75
68
  before(:each) do
76
69
  subject.stub(:oauth_access_token).and_return(request)
77
70
  subject.stub(:normalize_url).with("me").and_return("me")
78
- request.stub(:get)
71
+ request.stub(:get) { request }
79
72
  end
80
73
 
81
74
  it "should return a Hashie::Mash" do
82
- subject.request(:get, "me").class.should eql(Hashie::Mash)
83
- end
84
-
85
- end
86
-
87
- describe "when errors are set" do
88
- it "should call oauth_access_token.send with errors set" do
89
- subject = OAuthErrorTester.new(options)
90
- subject.stub(:normalize_url).and_return("error")
91
- subject.stub(:oauth_access_token).and_return(request)
92
- request.should_receive(:send).with(:get, "http://example.com/error", {:raise_errors => true})
93
- subject.request(:get, "error")
94
- end
95
-
96
- end
97
-
98
- describe "when a body is set" do
99
- it "should call oauth_access_token.send with errors set" do
100
- subject.stub(:normalize_url).and_return("users")
101
- subject.stub(:oauth_access_token).and_return(request)
102
- request.should_receive(:send).with(:get, "http://example.com/users", {:body => {"foo" => "bar"}.to_json, :raise_errors => false})
103
- subject.request(:get, "error", :body => {"foo" => "bar"})
75
+ subject.request(:get, "me").should eq 'data'
104
76
  end
105
-
106
77
  end
107
-
108
-
109
78
  end
110
79
  end
111
80
 
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ class MyCustomResponseError < Rapidash::ResponseError
4
+ def errors
5
+ if body.kind_of?(Array)
6
+ body.join(', ')
7
+ else
8
+ body
9
+ end
10
+ end
11
+ end
12
+
13
+ describe Rapidash::ResponseError do
14
+
15
+ context "standard response error class" do
16
+ let(:response) { Rapidash::ResponseError.new(env) }
17
+ let(:env) { { :status => '404', :method => 'post', :url => 'http://acme.com/api/posts', :body => 'Page not found' } }
18
+
19
+ describe ".initialize" do
20
+ it "should set attributes" do
21
+ expect(response.status).to eq 404
22
+ expect(response.method).to eq 'POST'
23
+ expect(response.url).to eq 'http://acme.com/api/posts'
24
+ expect(response.body).to eq 'Page not found'
25
+ end
26
+ end
27
+
28
+ describe "#message" do
29
+ it "should create a formatted error message" do
30
+ message = response.send(:message)
31
+ expect(message).to eq '404 POST http://acme.com/api/posts'
32
+ end
33
+ end
34
+ end
35
+
36
+ context "custom error class with #errors method" do
37
+ before :each do
38
+ Rapidash.response_exception_class = MyCustomResponseError
39
+ end
40
+
41
+ let(:response) { MyCustomResponseError.new(env) }
42
+ let(:env) { { :status => '404', :method => 'post', :url => 'http://acme.com/api/posts', :body => ['name cannot be blank', 'content cannot be blank'] } }
43
+
44
+ it "should call #errors" do
45
+ response.should_receive(:errors)
46
+ response.send(:message)
47
+ end
48
+
49
+ it "should create a formatted error message" do
50
+ message = response.send(:message)
51
+ expect(message).to eq '404 POST http://acme.com/api/posts | Errors: name cannot be blank, content cannot be blank'
52
+ end
53
+
54
+ after :each do
55
+ Rapidash.response_exception_class = nil
56
+ end
57
+
58
+ end
59
+ end
@@ -1,26 +1,29 @@
1
1
  require "spec_helper"
2
2
 
3
- class TestClientTester
3
+ class TesterClient
4
4
  include Rapidash::TestClient
5
5
  end
6
6
 
7
- describe Rapidash::HTTPClient do
7
+ describe Rapidash::TestClient do
8
+ let(:responses) do
9
+ { :get => { "foo" => "bar" } }
10
+ end
8
11
 
9
- let!(:responses) {
10
- {
11
- :get => {
12
- "foo" => "response"
13
- }
14
- }
15
- }
12
+ let(:client) { TesterClient.new(responses) }
16
13
 
17
- let!(:subject) { TestClientTester.new(:responses => responses) }
14
+ describe ".new" do
15
+ let(:stubs) { client.stubs }
18
16
 
19
- describe ".request" do
20
- it "should do something" do
21
- Rapidash::Response.should_receive(:new).with("response")
22
- subject.request(:get, "foo")
17
+ it "should create Faraday test stubs" do
18
+ expect(stubs).to be_a Faraday::Adapter::Test::Stubs
23
19
  end
24
20
  end
25
21
 
22
+ describe "#request" do
23
+ let(:response) { client.request(:get, '/foo') }
24
+
25
+ it "should respond with the correct data" do
26
+ expect(response).to eq 'bar'
27
+ end
28
+ end
26
29
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rapidash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0.beta
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gary 'Gazler' Rennie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-06-26 00:00:00.000000000 Z
11
+ date: 2013-07-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -73,7 +73,7 @@ dependencies:
73
73
  - - '>='
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
- type: :runtime
76
+ type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
@@ -94,6 +94,34 @@ dependencies:
94
94
  - - ~>
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0.8'
97
+ - !ruby/object:Gem::Dependency
98
+ name: faraday_middleware
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: '0.9'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: '0.9'
111
+ - !ruby/object:Gem::Dependency
112
+ name: faraday_middleware-multi_json
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: '0.0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ~>
123
+ - !ruby/object:Gem::Version
124
+ version: '0.0'
97
125
  - !ruby/object:Gem::Dependency
98
126
  name: oauth2
99
127
  requirement: !ruby/object:Gem::Requirement
@@ -126,16 +154,16 @@ dependencies:
126
154
  name: activesupport
127
155
  requirement: !ruby/object:Gem::Requirement
128
156
  requirements:
129
- - - ~>
157
+ - - '>='
130
158
  - !ruby/object:Gem::Version
131
- version: '3.0'
159
+ version: 3.0.0
132
160
  type: :runtime
133
161
  prerelease: false
134
162
  version_requirements: !ruby/object:Gem::Requirement
135
163
  requirements:
136
- - - ~>
164
+ - - '>='
137
165
  - !ruby/object:Gem::Version
138
- version: '3.0'
166
+ version: 3.0.0
139
167
  description: Evolve your API
140
168
  email:
141
169
  - gazler@gmail.com
@@ -151,25 +179,26 @@ files:
151
179
  - README.md
152
180
  - Rakefile
153
181
  - examples/github.rb
182
+ - lib/faraday/response/raise_rapidash_error.rb
154
183
  - lib/rapidash.rb
155
184
  - lib/rapidash/base.rb
156
185
  - lib/rapidash/client.rb
157
- - lib/rapidash/errors.rb
158
186
  - lib/rapidash/http_client.rb
159
187
  - lib/rapidash/oauth_client.rb
160
188
  - lib/rapidash/resourceable.rb
161
- - lib/rapidash/response.rb
189
+ - lib/rapidash/response_error.rb
162
190
  - lib/rapidash/test_client.rb
163
191
  - lib/rapidash/urlable.rb
164
192
  - lib/rapidash/version.rb
165
193
  - rapidash.gemspec
194
+ - spec/faraday/raise_rapidash_error_spec.rb
166
195
  - spec/rapidash/base_spec.rb
167
196
  - spec/rapidash/client_spec.rb
168
197
  - spec/rapidash/http_client_spec.rb
169
198
  - spec/rapidash/integration/test_client_spec.rb
170
199
  - spec/rapidash/oauth_client_spec.rb
171
200
  - spec/rapidash/resourceable_spec.rb
172
- - spec/rapidash/response_spec.rb
201
+ - spec/rapidash/response_error_spec.rb
173
202
  - spec/rapidash/test_client_spec.rb
174
203
  - spec/rapidash/urlable_spec.rb
175
204
  - spec/spec_helper.rb
@@ -188,23 +217,24 @@ required_ruby_version: !ruby/object:Gem::Requirement
188
217
  version: '0'
189
218
  required_rubygems_version: !ruby/object:Gem::Requirement
190
219
  requirements:
191
- - - '>='
220
+ - - '>'
192
221
  - !ruby/object:Gem::Version
193
- version: '0'
222
+ version: 1.3.1
194
223
  requirements: []
195
224
  rubyforge_project:
196
- rubygems_version: 2.0.0
225
+ rubygems_version: 2.0.2
197
226
  signing_key:
198
227
  specification_version: 4
199
228
  summary: An opinionated core for creating clients for RESTful APIs quickly
200
229
  test_files:
230
+ - spec/faraday/raise_rapidash_error_spec.rb
201
231
  - spec/rapidash/base_spec.rb
202
232
  - spec/rapidash/client_spec.rb
203
233
  - spec/rapidash/http_client_spec.rb
204
234
  - spec/rapidash/integration/test_client_spec.rb
205
235
  - spec/rapidash/oauth_client_spec.rb
206
236
  - spec/rapidash/resourceable_spec.rb
207
- - spec/rapidash/response_spec.rb
237
+ - spec/rapidash/response_error_spec.rb
208
238
  - spec/rapidash/test_client_spec.rb
209
239
  - spec/rapidash/urlable_spec.rb
210
240
  - spec/spec_helper.rb
@@ -1,5 +0,0 @@
1
- module Rapidash
2
- class ParseError < StandardError; end
3
- class ConfigurationError < StandardError; end
4
- class ResponseError < StandardError; end
5
- end
@@ -1,29 +0,0 @@
1
- require 'json'
2
- require 'hashie'
3
-
4
- module Rapidash
5
- class Response
6
- class << self
7
- def new(response)
8
- return nil unless response.body
9
- return nil if response.body.empty?
10
- return nil if response.body == "null"
11
- type = response.headers["content-type"]
12
- body = JSON.parse(response.body)
13
- if body.kind_of?(Hash)
14
- return Hashie::Mash.new(body)
15
- elsif body.kind_of?(Array)
16
- output = []
17
- body.each do |el|
18
- output << Hashie::Mash.new(el)
19
- end
20
- return output
21
- end
22
- rescue JSON::ParserError => e
23
- raise ParseError.new("Failed to parse content for type: #{type}")
24
- end
25
- end
26
-
27
- end
28
- end
29
-
@@ -1,145 +0,0 @@
1
- require 'json'
2
- require "spec_helper"
3
-
4
- def valid_response_object
5
- body = {"foo" => "bar" }.to_json
6
- OpenStruct.new({
7
- :headers => {
8
- "content-type" => "application/json"
9
- },
10
- :body => body
11
- })
12
- end
13
-
14
- def valid_html_response_object
15
- body = {"foo" => "bar" }.to_json
16
- OpenStruct.new({
17
- :headers => {
18
- "content-type" => "text/html"
19
- },
20
- :body => body
21
- })
22
- end
23
-
24
- def valid_js_response_object
25
- body = {"foo" => "bar" }.to_json
26
- OpenStruct.new({
27
- :headers => {
28
- "content-type" => "text/javascript"
29
- },
30
- :body => body
31
- })
32
- end
33
-
34
- def valid_null_response_object
35
- body = nil.to_json
36
- OpenStruct.new({
37
- :headers => {
38
- "content-type" => "application/json"
39
- },
40
- :body => body
41
- })
42
- end
43
-
44
- def valid_empty_response_object
45
- body = ""
46
- OpenStruct.new({
47
- :headers => {
48
- "content-type" => "application/json"
49
- },
50
- :body => body
51
- })
52
- end
53
-
54
-
55
- def valid_response_array
56
- body = [{"foo" => "bar" }, {"baz" => "bra"}].to_json
57
- OpenStruct.new({
58
- :headers => {
59
- "content-type" => "application/json"
60
- },
61
- :body => body
62
- })
63
- end
64
-
65
-
66
- def invalid_response
67
- OpenStruct.new({
68
- :headers => {
69
- "content-type" => "application/xml"
70
- },
71
- :body => "<xml>something</xml>"
72
- })
73
- end
74
-
75
- def invalid_js_response_object
76
- OpenStruct.new({
77
- :headers => {
78
- "content-type" => "text/javascript"
79
- },
80
- :body => "<xml>something</xml>"
81
- })
82
- end
83
-
84
- def nil_response
85
- OpenStruct.new({
86
- :body => nil
87
- })
88
- end
89
-
90
- describe Rapidash::Response do
91
-
92
- describe "#new" do
93
- it "should parse JSON Objects" do
94
- response = Rapidash::Response.new(valid_response_object)
95
- response.foo.should eql("bar")
96
- end
97
-
98
- it "should parse JSON Objects returned with javascript type" do
99
- response = Rapidash::Response.new(valid_js_response_object)
100
- response.foo.should eql("bar")
101
- end
102
-
103
- it "should parse JSON Objects returned with html type" do
104
- response = Rapidash::Response.new(valid_html_response_object)
105
- response.foo.should eql("bar")
106
- end
107
-
108
- it "should parse a JSON null" do
109
- response = Rapidash::Response.new(valid_null_response_object)
110
- response.should eql(nil)
111
- end
112
-
113
- it "should parse an empty body" do
114
- response = Rapidash::Response.new(valid_empty_response_object)
115
- response.should eql(nil)
116
- end
117
-
118
-
119
- it "should parse JSON Arrays" do
120
- response = Rapidash::Response.new(valid_response_array)
121
- response[0].foo.should eql("bar")
122
- response[1].baz.should eql("bra")
123
- end
124
-
125
- it "should return nil if the response has no body" do
126
- response = Rapidash::Response.new(nil_response)
127
- response.should eql(nil)
128
- end
129
-
130
-
131
- it "should raise an error on a non-json response" do
132
- expect {
133
- Rapidash::Response.new(invalid_response)
134
- }.to raise_error(Rapidash::ParseError)
135
- end
136
-
137
- it "should raise an error on a non-json response body" do
138
- expect {
139
- Rapidash::Response.new(invalid_js_response_object)
140
- }.to raise_error(Rapidash::ParseError)
141
- end
142
- end
143
-
144
-
145
- end