rapidash 0.0.1
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 +7 -0
- data/.gitignore +17 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +116 -0
- data/Rakefile +1 -0
- data/lib/rapidash.rb +17 -0
- data/lib/rapidash/base.rb +20 -0
- data/lib/rapidash/client.rb +9 -0
- data/lib/rapidash/clientable.rb +37 -0
- data/lib/rapidash/errors.rb +4 -0
- data/lib/rapidash/http_client.rb +39 -0
- data/lib/rapidash/oauth_client.rb +54 -0
- data/lib/rapidash/response.rb +29 -0
- data/lib/rapidash/urlable.rb +28 -0
- data/lib/rapidash/version.rb +3 -0
- data/rapidash.gemspec +29 -0
- data/spec/rapidash/base_spec.rb +49 -0
- data/spec/rapidash/client_spec.rb +9 -0
- data/spec/rapidash/clientable_spec.rb +99 -0
- data/spec/rapidash/http_client_spec.rb +72 -0
- data/spec/rapidash/oauth_client_spec.rb +104 -0
- data/spec/rapidash/response_spec.rb +57 -0
- data/spec/rapidash/urlable_spec.rb +42 -0
- data/spec/spec_helper.rb +2 -0
- metadata +161 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: eb726775f243e6328acdfa4a53fba2ecbb81727d
|
4
|
+
data.tar.gz: fe0fdea46f6798d999095c5acf7d337c291cba14
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 16a571aab676ca4d1f8f4209abbe3104184920c78f65349dbf50f12f6abf089f4347fefc66f57b154a55fd0752a3a548432a29fdd783748293de30f9d9ac0b74
|
7
|
+
data.tar.gz: fd8f336dc1436a0ca683c16a692006851dd6f3e9e5eddf0afc7d558740b1006dbbb66b4b92bf47a5656f04d91e1891c06952b3a15d7714788accc4a6c96f289f
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Gary 'Gazler' Rennie
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
# Rapidash
|
2
|
+
|
3
|
+
Rapidash is an opinionated core for you to build a client for your API on. The goal is to define a standard way that developers can quickly write a client for the consumption of their RESTful API.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'rapidash'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install rapidash
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
### Resources
|
22
|
+
|
23
|
+
Resources can be defined as follows:
|
24
|
+
|
25
|
+
class Users < Rapidash::Base
|
26
|
+
url "users"
|
27
|
+
end
|
28
|
+
|
29
|
+
### Client
|
30
|
+
|
31
|
+
The main thing a client must do is define a method, `oauth` and `http` are currently supported. You can also define resources which links a resource as defined above to the client.
|
32
|
+
|
33
|
+
class Client < Rapidash::Client
|
34
|
+
method :oauth
|
35
|
+
resource :users
|
36
|
+
end
|
37
|
+
|
38
|
+
OAuth provides an initialize method which you can see in the Facebook client example.
|
39
|
+
|
40
|
+
Currently when using the HTTP method, you will need to define your own initialize method to set the site in use.
|
41
|
+
|
42
|
+
### Making calls
|
43
|
+
|
44
|
+
client = Client.new
|
45
|
+
client.site = "http://example.com/"
|
46
|
+
client.users #Returns an instance of Users
|
47
|
+
client.users! #Will make a call to "http://example.com/users
|
48
|
+
client.users!(1) #Will make a call to http://example.com/users/1
|
49
|
+
client.users!(params => {:page => 1}}) # Will make a call to http://example.com/users?page=1
|
50
|
+
|
51
|
+
## Example Clients
|
52
|
+
|
53
|
+
### Facebook
|
54
|
+
|
55
|
+
require 'rapidash'
|
56
|
+
|
57
|
+
class Me < Rapidash::Base
|
58
|
+
url "me"
|
59
|
+
end
|
60
|
+
|
61
|
+
class Facebook < Rapidash::Client
|
62
|
+
method :oauth
|
63
|
+
resource :me
|
64
|
+
end
|
65
|
+
|
66
|
+
client = Facebook`.new({
|
67
|
+
:site => "https://graph.facebook.com",
|
68
|
+
:uid => "YOUR_ID",
|
69
|
+
:secret => "YOUR_SECRET",
|
70
|
+
:access_token => "YOUR_TOKEN"
|
71
|
+
})
|
72
|
+
p client.me!.first_name #Gary
|
73
|
+
|
74
|
+
### Github
|
75
|
+
|
76
|
+
require 'rapidash'
|
77
|
+
|
78
|
+
class Users < Rapidash::Base
|
79
|
+
url :users
|
80
|
+
|
81
|
+
def user(name)
|
82
|
+
self.url += "/#{name}"
|
83
|
+
self
|
84
|
+
end
|
85
|
+
|
86
|
+
def repos!
|
87
|
+
self.url += "/repos"
|
88
|
+
call!
|
89
|
+
end
|
90
|
+
|
91
|
+
def user!(name)
|
92
|
+
user(name)
|
93
|
+
call!
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class Github < Rapidash::Client
|
98
|
+
method :http
|
99
|
+
resource :users
|
100
|
+
|
101
|
+
def initialize
|
102
|
+
@site = "https://api.github.com/"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
client = Github.new
|
107
|
+
p client.users.user!("Gazler").name #Gary Rennie
|
108
|
+
p client.users.user("Gazler").repos![0].name #Githug
|
109
|
+
|
110
|
+
## Contributing
|
111
|
+
|
112
|
+
1. Fork it
|
113
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
114
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
115
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
116
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/lib/rapidash.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require "rapidash/version"
|
2
|
+
|
3
|
+
require "rapidash/errors"
|
4
|
+
|
5
|
+
require "rapidash/response"
|
6
|
+
|
7
|
+
require "rapidash/clientable"
|
8
|
+
require "rapidash/client"
|
9
|
+
|
10
|
+
require "rapidash/urlable"
|
11
|
+
require "rapidash/base"
|
12
|
+
|
13
|
+
require "rapidash/http_client"
|
14
|
+
require "rapidash/oauth_client"
|
15
|
+
|
16
|
+
module Rapidash
|
17
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Rapidash
|
2
|
+
class Base
|
3
|
+
|
4
|
+
include Urlable
|
5
|
+
attr_accessor :url, :options, :client
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
raise ConfigurationError.new "Missing URL attribute on the resource, set it by calling `url` in your resource class"
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
def call!
|
13
|
+
self.options ||= {}
|
14
|
+
self.options[:header] ||= {}
|
15
|
+
self.options[:header]["content-type"] = "application/json"
|
16
|
+
method = self.options.delete(:method) || :get
|
17
|
+
client.send(method, url, self.options)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Rapidash
|
2
|
+
module Clientable
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
|
10
|
+
def method(method)
|
11
|
+
if method == :http
|
12
|
+
include HTTPClient
|
13
|
+
elsif method == :oauth
|
14
|
+
include OAuthClient
|
15
|
+
else
|
16
|
+
raise ConfigurationError.new "Invalid API Authentication Method"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def resource(name)
|
21
|
+
mod = self.to_s.split("::")[0...-1]
|
22
|
+
if mod.empty?
|
23
|
+
mod = Kernel
|
24
|
+
else
|
25
|
+
mod = Kernel.const_get(mod.join("::"))
|
26
|
+
end
|
27
|
+
klass = mod.const_get(name.capitalize)
|
28
|
+
define_method(name) do |*args|
|
29
|
+
klass.new(self, *args)
|
30
|
+
end
|
31
|
+
define_method("#{name}!".to_sym) do |*args|
|
32
|
+
klass.new(self, *args).call!
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
module Rapidash
|
4
|
+
module HTTPClient
|
5
|
+
|
6
|
+
attr_accessor :site
|
7
|
+
attr_writer :connection
|
8
|
+
|
9
|
+
def site=(value)
|
10
|
+
@connection = nil
|
11
|
+
@site = value
|
12
|
+
end
|
13
|
+
|
14
|
+
def connection
|
15
|
+
@connection ||= Faraday.new(site)
|
16
|
+
end
|
17
|
+
|
18
|
+
def get(url, options = {})
|
19
|
+
request(:get, url, options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def post(url, options = {})
|
23
|
+
request(:post, url, options)
|
24
|
+
end
|
25
|
+
|
26
|
+
def request(verb, url, options = {})
|
27
|
+
url = connection.build_url(url, options[:params]).to_s
|
28
|
+
response = connection.run_request(verb, url, options[:body], options[:header])
|
29
|
+
|
30
|
+
case response.status.to_s[0]
|
31
|
+
#Handle redirects
|
32
|
+
when "3"
|
33
|
+
request(verb, response.headers["location"], options)
|
34
|
+
when "2"
|
35
|
+
return Response.new(response)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'oauth2'
|
2
|
+
require 'hashie'
|
3
|
+
|
4
|
+
module Rapidash
|
5
|
+
module OAuthClient
|
6
|
+
|
7
|
+
attr_accessor :secret, :uid, :access_token, :site
|
8
|
+
|
9
|
+
def initialize(options)
|
10
|
+
[:uid, :secret, :site].each do |key|
|
11
|
+
if options[key]
|
12
|
+
self.send("#{key.to_s}=".to_sym, options[key])
|
13
|
+
else
|
14
|
+
raise ConfigurationError.new "Missing #{key} value"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
self.access_token = options[:access_token] if options[:access_token]
|
18
|
+
end
|
19
|
+
|
20
|
+
def get(url, params = {})
|
21
|
+
request(:get, url, :params => params)
|
22
|
+
end
|
23
|
+
|
24
|
+
def request(verb, url, options = {})
|
25
|
+
response = oauth_access_token.send(verb.to_sym, "#{site}/#{url}", options)
|
26
|
+
body = JSON.parse(response.body)
|
27
|
+
if body.kind_of?(Hash)
|
28
|
+
return Hashie::Mash.new(body)
|
29
|
+
elsif body.kind_of?(Array)
|
30
|
+
output = []
|
31
|
+
body.each do |el|
|
32
|
+
output << Hashie::Mash.new(el)
|
33
|
+
end
|
34
|
+
return output
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def access_token_from_code(code, url)
|
39
|
+
token = client.auth_code.get_token(code, :redirect_uri => url)
|
40
|
+
self.access_token = token.token
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def client
|
46
|
+
@oauth_client ||= ::OAuth2::Client.new(uid, secret, :site => site)
|
47
|
+
end
|
48
|
+
|
49
|
+
def oauth_access_token
|
50
|
+
@oauth_access_token ||= ::OAuth2::AccessToken.new(client, access_token)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'hashie'
|
3
|
+
|
4
|
+
module Rapidash
|
5
|
+
class Response
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def new(response)
|
9
|
+
type = response.headers["content-type"]
|
10
|
+
if type.include?("application/json")
|
11
|
+
body = JSON.parse(response.body)
|
12
|
+
if body.kind_of?(Hash)
|
13
|
+
return Hashie::Mash.new(body)
|
14
|
+
elsif body.kind_of?(Array)
|
15
|
+
output = []
|
16
|
+
body.each do |el|
|
17
|
+
output << Hashie::Mash.new(el)
|
18
|
+
end
|
19
|
+
return output
|
20
|
+
end
|
21
|
+
else
|
22
|
+
raise ParseError.new("Cannot parse content type: #{response.headers["content-type"]}")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Rapidash
|
2
|
+
module Urlable
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def url(url)
|
10
|
+
self.class_eval do
|
11
|
+
define_method(:initialize) do |*args|
|
12
|
+
@client, id, options = args
|
13
|
+
if id.is_a?(Hash)
|
14
|
+
options = id
|
15
|
+
id = nil
|
16
|
+
end
|
17
|
+
@options ||= {}
|
18
|
+
options ||= {}
|
19
|
+
@options.merge!(options)
|
20
|
+
@url = url.to_s
|
21
|
+
@url += "/#{id}" if id
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
data/rapidash.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rapidash/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "rapidash"
|
8
|
+
spec.version = Rapidash::VERSION
|
9
|
+
spec.authors = ["Gary 'Gazler' Rennie"]
|
10
|
+
spec.email = ["gazler@gmail.com"]
|
11
|
+
spec.description = %q{Evolve your API}
|
12
|
+
spec.summary = %q{An opinionated core for creating clients for RESTful APIs quickly}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec", "~> 2.8"
|
24
|
+
|
25
|
+
spec.add_dependency 'faraday', '~> 0.8'
|
26
|
+
spec.add_dependency "oauth2", "~>0.6"
|
27
|
+
spec.add_dependency "hashie", "~>1.2"
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class BaseTester < Rapidash::Base
|
4
|
+
url "tester"
|
5
|
+
end
|
6
|
+
|
7
|
+
class InvalidApiTester < Rapidash::Base
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
describe Rapidash::Base do
|
12
|
+
|
13
|
+
describe ".initialize" do
|
14
|
+
|
15
|
+
it "should raise an error" do
|
16
|
+
expect {
|
17
|
+
InvalidApiTester.new
|
18
|
+
}.to raise_error(Rapidash::ConfigurationError)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should not raise an error if url has been called" do
|
22
|
+
expect {
|
23
|
+
BaseTester.new.should be_valid
|
24
|
+
}.to_not raise_error(Rapidash::ConfigurationError)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
let(:client) { mock }
|
30
|
+
let(:headers) { {"content-type" => "application/json"} }
|
31
|
+
let (:subject) { BaseTester.new(client) }
|
32
|
+
|
33
|
+
describe ".call!" do
|
34
|
+
it "should call get on the client" do
|
35
|
+
subject.url = "tester/1"
|
36
|
+
client.should_receive(:get).with("tester/1", {:header => headers})
|
37
|
+
subject.call!
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
it "should call a post on the client if set" do
|
42
|
+
client.should_receive(:post).with("tester", {:header => headers})
|
43
|
+
subject.options = {:method => :post}
|
44
|
+
subject.url = "tester"
|
45
|
+
subject.call!
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
class Rapidash::Users
|
4
|
+
def initialize(*args)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
class Users
|
9
|
+
def initialize(*args)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Rapidash::ClientTester
|
14
|
+
include Rapidash::Clientable
|
15
|
+
resource :users
|
16
|
+
end
|
17
|
+
|
18
|
+
class ClientTester
|
19
|
+
include Rapidash::Clientable
|
20
|
+
resource :users
|
21
|
+
end
|
22
|
+
|
23
|
+
class OAuthClientTester
|
24
|
+
include Rapidash::Clientable
|
25
|
+
method :oauth
|
26
|
+
end
|
27
|
+
|
28
|
+
class HTTPClientTester
|
29
|
+
include Rapidash::Clientable
|
30
|
+
method :http
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
describe Rapidash::Clientable do
|
36
|
+
|
37
|
+
describe "#included" do
|
38
|
+
it "should include the resource method" do
|
39
|
+
Rapidash::ClientTester.methods.should include(:resource)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should include the method method" do
|
43
|
+
Rapidash::ClientTester.methods.should include(:method)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "#resource" do
|
48
|
+
it "should add a method with the name of the argument" do
|
49
|
+
Rapidash::ClientTester.new.methods.should include(:users)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should add a bang method with the name of the argument" do
|
53
|
+
Rapidash::ClientTester.new.methods.should include(:users!)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#method" do
|
58
|
+
|
59
|
+
it "should include the HTTPClient" do
|
60
|
+
client = HTTPClientTester.new
|
61
|
+
client.class.ancestors.should include(Rapidash::HTTPClient)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should include the OAuthClient" do
|
65
|
+
client = OAuthClientTester.new({:uid => "foo", :secret => "bar", :site => "baz"})
|
66
|
+
client.class.ancestors.should include(Rapidash::OAuthClient)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should raise an error on anything else" do
|
70
|
+
expect {
|
71
|
+
class InvalidClientTester
|
72
|
+
include Rapidash::Clientable
|
73
|
+
method :invalid
|
74
|
+
end
|
75
|
+
}.to raise_error(Rapidash::ConfigurationError)
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
describe ".users" do
|
81
|
+
it "should return an instance of the resource" do
|
82
|
+
Rapidash::ClientTester.new.users.class.should eql(Rapidash::Users)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should not use a namespace if not in a module" do
|
86
|
+
ClientTester.new.users.class.should eql(Users)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe ".tickets!" do
|
91
|
+
it "should return an instance of the resource and call it" do
|
92
|
+
users = mock
|
93
|
+
Rapidash::Users.should_receive(:new).and_return(users)
|
94
|
+
users.should_receive(:call!)
|
95
|
+
Rapidash::ClientTester.new.users!
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
class HTTPTester
|
4
|
+
include Rapidash::HTTPClient
|
5
|
+
end
|
6
|
+
|
7
|
+
describe Rapidash::HTTPClient do
|
8
|
+
|
9
|
+
let!(:subject) { HTTPTester.new }
|
10
|
+
|
11
|
+
describe ".site=" do
|
12
|
+
it "should clear the connection variable" do
|
13
|
+
subject.instance_variable_get(:@connection).should eql(nil)
|
14
|
+
subject.connection
|
15
|
+
subject.instance_variable_get(:@connection).class.should eql(Faraday::Connection)
|
16
|
+
subject.site = "foo"
|
17
|
+
subject.instance_variable_get(:@connection).should eql(nil)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should set the site variable" do
|
21
|
+
subject.instance_variable_get(:@site).should eql(nil)
|
22
|
+
subject.site = "foo"
|
23
|
+
subject.instance_variable_get(:@site).should eql("foo")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe ".connection" do
|
28
|
+
it "should create a Faraday object" do
|
29
|
+
subject.connection.class.should eql(Faraday::Connection)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe ".get" do
|
34
|
+
it "should call request" do
|
35
|
+
subject.should_receive(:request).with(:get, "foo", {})
|
36
|
+
subject.get("foo")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe ".get" do
|
41
|
+
it "should call request" do
|
42
|
+
subject.should_receive(:request).with(:post, "foo", {})
|
43
|
+
subject.post("foo")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
describe ".request" do
|
49
|
+
|
50
|
+
let!(:valid_response) { OpenStruct.new(:status => "200")}
|
51
|
+
let!(:redirect_response) { OpenStruct.new(:status => "301", :headers => {"location" => "http://example.com/redirect"})}
|
52
|
+
|
53
|
+
before(:each) do
|
54
|
+
subject.site = "http://example.com"
|
55
|
+
Rapidash::Response.should_receive(:new).and_return("response")
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should return a response object" do
|
59
|
+
subject.connection.should_receive(:run_request).with(:get, "http://example.com/foo", nil, nil).and_return(valid_response)
|
60
|
+
response = subject.request(:get, "foo")
|
61
|
+
response.should eql("response")
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should perform a redirect" do
|
65
|
+
subject.connection.should_receive(:run_request).with(:get, "http://example.com/foo", nil, nil).and_return(redirect_response)
|
66
|
+
subject.connection.should_receive(:run_request).with(:get, "http://example.com/redirect", nil, nil).and_return(valid_response)
|
67
|
+
response = subject.request(:get, "foo")
|
68
|
+
response.should eql("response")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class OAuthTester
|
4
|
+
include Rapidash::OAuthClient
|
5
|
+
end
|
6
|
+
|
7
|
+
describe Rapidash::OAuthClient do
|
8
|
+
|
9
|
+
let(:options) do
|
10
|
+
Hash({
|
11
|
+
:uid => "foo",
|
12
|
+
:secret => "bar",
|
13
|
+
:access_token => "baz",
|
14
|
+
:site => "http://example.com"
|
15
|
+
})
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:subject) { OAuthTester.new(options) }
|
19
|
+
|
20
|
+
|
21
|
+
describe ".site" do
|
22
|
+
it "should be example.com" do
|
23
|
+
subject.site.should eql("http://example.com")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe ".access_token_from_code" do
|
28
|
+
it "should call livestax for the access token" do
|
29
|
+
auth_code = mock
|
30
|
+
client = mock
|
31
|
+
subject.stub(:client).and_return(client)
|
32
|
+
client.should_receive(:auth_code).and_return(auth_code)
|
33
|
+
auth_code.should_receive(:get_token).with("123", :redirect_uri => "http://localhost").and_return(OpenStruct.new(:token => "token"))
|
34
|
+
subject.access_token_from_code("123", "http://localhost").should eql("token")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe ".client" do
|
39
|
+
it "should be an OAuth2::Client" do
|
40
|
+
subject.send(:client).class.should eql(OAuth2::Client)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe ".oauth_access_token" do
|
45
|
+
it "should be an OAuth2::AccessToken" do
|
46
|
+
subject.send(:oauth_access_token).class.should eql(OAuth2::AccessToken)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe ".get" do
|
51
|
+
it "should call request with the parameters" do
|
52
|
+
subject.should_receive(:request).with(:get, "me", :params => {:page => 1})
|
53
|
+
subject.get("me", {:page => 1})
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe ".request" do
|
58
|
+
|
59
|
+
let(:request) { mock }
|
60
|
+
|
61
|
+
describe "object returned from API call" do
|
62
|
+
|
63
|
+
let(:body) { {:foo => "bar"}.to_json }
|
64
|
+
let(:response) { OpenStruct.new(:body => body) }
|
65
|
+
|
66
|
+
before(:each) do
|
67
|
+
subject.stub(:oauth_access_token).and_return(request)
|
68
|
+
request.stub(:get).and_return(response)
|
69
|
+
end
|
70
|
+
it "should return a Hashie::Mash" do
|
71
|
+
subject.request(:get, "me").class.should eql(Hashie::Mash)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should return a traversable object" do
|
75
|
+
subject.request(:get, "me").foo.should eql("bar")
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "array returned from API call" do
|
81
|
+
|
82
|
+
let(:body) { [{:foo => "bar"}, {:baz => "bra"}].to_json }
|
83
|
+
let(:response) { OpenStruct.new(:body => body) }
|
84
|
+
|
85
|
+
before(:each) do
|
86
|
+
subject.stub(:oauth_access_token).and_return(request)
|
87
|
+
request.stub(:get).and_return(response)
|
88
|
+
end
|
89
|
+
it "should return an array" do
|
90
|
+
subject.request(:get, "me").class.should eql(Array)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should return a traversable object" do
|
94
|
+
response = subject.request(:get, "me")
|
95
|
+
response[0].foo.should eql("bar")
|
96
|
+
response[1].baz.should eql("bra")
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
end
|
104
|
+
|
@@ -0,0 +1,57 @@
|
|
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
|
+
|
15
|
+
def valid_response_array
|
16
|
+
body = [{"foo" => "bar" }, {"baz" => "bra"}].to_json
|
17
|
+
OpenStruct.new({
|
18
|
+
:headers => {
|
19
|
+
"content-type" => "application/json"
|
20
|
+
},
|
21
|
+
:body => body
|
22
|
+
})
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
def invalid_response
|
27
|
+
OpenStruct.new({
|
28
|
+
:headers => {
|
29
|
+
"content-type" => "application/xml"
|
30
|
+
}
|
31
|
+
})
|
32
|
+
end
|
33
|
+
|
34
|
+
describe Rapidash::Response do
|
35
|
+
|
36
|
+
describe "#new" do
|
37
|
+
it "should parse JSON Objects" do
|
38
|
+
response = Rapidash::Response.new(valid_response_object)
|
39
|
+
response.foo.should eql("bar")
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should parse JSON Arrays" do
|
43
|
+
response = Rapidash::Response.new(valid_response_array)
|
44
|
+
response[0].foo.should eql("bar")
|
45
|
+
response[1].baz.should eql("bra")
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
it "should raise an error on a non-json response" do
|
50
|
+
expect {
|
51
|
+
Rapidash::Response.new(invalid_response)
|
52
|
+
}.to raise_error(Rapidash::ParseError)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class ApiTester
|
4
|
+
attr_accessor :url, :options, :client
|
5
|
+
include Rapidash::Urlable
|
6
|
+
url :foo
|
7
|
+
end
|
8
|
+
|
9
|
+
class ApiTesterNoUrl
|
10
|
+
include Rapidash::Urlable
|
11
|
+
end
|
12
|
+
|
13
|
+
describe Rapidash::Urlable do
|
14
|
+
|
15
|
+
let!(:client) { mock }
|
16
|
+
|
17
|
+
describe "#included" do
|
18
|
+
it "should add the url method" do
|
19
|
+
ApiTester.methods.should include(:url)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#url" do
|
24
|
+
it "should override the initialize to set a url" do
|
25
|
+
ApiTesterNoUrl.new.instance_variable_get(:@url).should eql(nil)
|
26
|
+
ApiTester.new.instance_variable_get(:@url).should eql("foo")
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should set options on the class" do
|
30
|
+
api = ApiTester.new(client, :option1 => "foo")
|
31
|
+
api.instance_variable_get(:@options).should eql({:option1 => "foo"})
|
32
|
+
api.instance_variable_get(:@url).should eql("foo")
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should let an id be set on initialization" do
|
36
|
+
api = ApiTester.new(client, 1, :option1 => "foo")
|
37
|
+
api.instance_variable_get(:@options).should eql({:option1 => "foo"})
|
38
|
+
api.instance_variable_get(:@url).should eql("foo/1")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rapidash
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gary 'Gazler' Rennie
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-03-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.8'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.8'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: faraday
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.8'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.8'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: oauth2
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.6'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.6'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: hashie
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.2'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ~>
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.2'
|
97
|
+
description: Evolve your API
|
98
|
+
email:
|
99
|
+
- gazler@gmail.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- .gitignore
|
105
|
+
- .rspec
|
106
|
+
- Gemfile
|
107
|
+
- LICENSE.txt
|
108
|
+
- README.md
|
109
|
+
- Rakefile
|
110
|
+
- lib/rapidash.rb
|
111
|
+
- lib/rapidash/base.rb
|
112
|
+
- lib/rapidash/client.rb
|
113
|
+
- lib/rapidash/clientable.rb
|
114
|
+
- lib/rapidash/errors.rb
|
115
|
+
- lib/rapidash/http_client.rb
|
116
|
+
- lib/rapidash/oauth_client.rb
|
117
|
+
- lib/rapidash/response.rb
|
118
|
+
- lib/rapidash/urlable.rb
|
119
|
+
- lib/rapidash/version.rb
|
120
|
+
- rapidash.gemspec
|
121
|
+
- spec/rapidash/base_spec.rb
|
122
|
+
- spec/rapidash/client_spec.rb
|
123
|
+
- spec/rapidash/clientable_spec.rb
|
124
|
+
- spec/rapidash/http_client_spec.rb
|
125
|
+
- spec/rapidash/oauth_client_spec.rb
|
126
|
+
- spec/rapidash/response_spec.rb
|
127
|
+
- spec/rapidash/urlable_spec.rb
|
128
|
+
- spec/spec_helper.rb
|
129
|
+
homepage: ''
|
130
|
+
licenses:
|
131
|
+
- MIT
|
132
|
+
metadata: {}
|
133
|
+
post_install_message:
|
134
|
+
rdoc_options: []
|
135
|
+
require_paths:
|
136
|
+
- lib
|
137
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - '>='
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0'
|
147
|
+
requirements: []
|
148
|
+
rubyforge_project:
|
149
|
+
rubygems_version: 2.0.2
|
150
|
+
signing_key:
|
151
|
+
specification_version: 4
|
152
|
+
summary: An opinionated core for creating clients for RESTful APIs quickly
|
153
|
+
test_files:
|
154
|
+
- spec/rapidash/base_spec.rb
|
155
|
+
- spec/rapidash/client_spec.rb
|
156
|
+
- spec/rapidash/clientable_spec.rb
|
157
|
+
- spec/rapidash/http_client_spec.rb
|
158
|
+
- spec/rapidash/oauth_client_spec.rb
|
159
|
+
- spec/rapidash/response_spec.rb
|
160
|
+
- spec/rapidash/urlable_spec.rb
|
161
|
+
- spec/spec_helper.rb
|