rapidash 0.1.2 → 0.2.0
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 +4 -4
- data/.gitignore +1 -0
- data/README.md +46 -9
- data/examples/github.rb +6 -6
- data/lib/rapidash.rb +3 -1
- data/lib/rapidash/base.rb +10 -8
- data/lib/rapidash/client.rb +54 -2
- data/lib/rapidash/http_client.rb +15 -30
- data/lib/rapidash/oauth_client.rb +10 -10
- data/lib/rapidash/resourceable.rb +32 -14
- data/lib/rapidash/response.rb +12 -11
- data/lib/rapidash/test_client.rb +0 -1
- data/lib/rapidash/urlable.rb +0 -2
- data/lib/rapidash/version.rb +1 -1
- data/rapidash.gemspec +2 -0
- data/spec/rapidash/base_spec.rb +19 -7
- data/spec/rapidash/client_spec.rb +99 -0
- data/spec/rapidash/http_client_spec.rb +41 -56
- data/spec/rapidash/integration/test_client_spec.rb +2 -2
- data/spec/rapidash/oauth_client_spec.rb +27 -27
- data/spec/rapidash/resourceable_spec.rb +140 -9
- data/spec/rapidash/response_spec.rb +31 -0
- data/spec/rapidash/urlable_spec.rb +1 -1
- data/spec/spec_helper.rb +4 -1
- metadata +31 -6
- data/lib/rapidash/clientable.rb +0 -35
- data/spec/rapidash/clientable_spec.rb +0 -88
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a317197b608c00d1116ad4be65b62238b0a98034
|
4
|
+
data.tar.gz: cdc69d6da7a4e33c58d83d0fc89e1b0a70cfb72c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c85000a1ed1351fadcfc1567a4469d54c4920a23eb8e6aa6e60de579b2b6abdd4867179eb7bbc2c844c6c9d745d8ec95ef4114d6c05312c4abdb4e33a3a06751
|
7
|
+
data.tar.gz: 71ef9f5d5e1669de47f6681a86c9c541b7712d9cc29b57add9cc4cd86ac15acbb73f20fc0c972881bfebbd38088dc86c92e720f9476781c84cbe2766d1ed94cc
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -25,6 +25,10 @@ A screencast on Rapidash is available to watch in mp4 and ogv formats.
|
|
25
25
|
* [Rapidash Screencast mp4](http://screencasts.gazler.com/rapidash.mp4)
|
26
26
|
* [Rapidash Screencast ogv](http://screencasts.gazler.com/rapidash.ogv)
|
27
27
|
|
28
|
+
### Sample Rails app
|
29
|
+
|
30
|
+
A sample rails app is available at [https://github.com/Gazler/rapidash-tester](https://github.com/Gazler/rapidash-tester) it provides a rails server and a Rapidash client. Please note that the client is also used as a form of integration test for rapidash.
|
31
|
+
|
28
32
|
### Resources
|
29
33
|
|
30
34
|
Resources can be defined as follows:
|
@@ -37,7 +41,7 @@ end
|
|
37
41
|
The URL of the resource will be inferred from the class name. In this case Users. If you want to override that, you can with the url method.
|
38
42
|
|
39
43
|
```ruby
|
40
|
-
class
|
44
|
+
class User < Rapidash::Base
|
41
45
|
url :members # or url "members" is also supported
|
42
46
|
end
|
43
47
|
```
|
@@ -45,10 +49,10 @@ end
|
|
45
49
|
Resources can exist inside other resources. For example, on Github, a user has repositories. The following could be how you build the resources:
|
46
50
|
|
47
51
|
```ruby
|
48
|
-
class
|
52
|
+
class Repo < Rapidash::Base
|
49
53
|
end
|
50
54
|
|
51
|
-
class
|
55
|
+
class User < Rapidash::Base
|
52
56
|
resource :repos
|
53
57
|
end
|
54
58
|
```
|
@@ -58,7 +62,7 @@ end
|
|
58
62
|
A root element can be set for create and post actions
|
59
63
|
|
60
64
|
```ruby
|
61
|
-
class
|
65
|
+
class Post < Rapidash::Base
|
62
66
|
end
|
63
67
|
|
64
68
|
client.posts.create!({:post => {:name => "a post"}})
|
@@ -67,13 +71,28 @@ client.posts.create!({:post => {:name => "a post"}})
|
|
67
71
|
With a root element, the code would look like this:
|
68
72
|
|
69
73
|
```ruby
|
70
|
-
class
|
74
|
+
class Post < Rapidash::Base
|
71
75
|
root :post
|
72
76
|
end
|
73
77
|
|
74
78
|
client.posts.create!(:name => "a post")
|
75
79
|
```
|
76
80
|
|
81
|
+
### Class Names and Classes In Different Modules
|
82
|
+
|
83
|
+
If you wish to use a class in a different module or a class with a different name as the class for your resource then you can use the `:class_name` option.
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
module MyModule
|
87
|
+
class MyResource < Rapidash::Base
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class AnotherResource < Rapidash::Base
|
92
|
+
resource :my_cool_resource, :class_name => "MyModule::MyResource"
|
93
|
+
end
|
94
|
+
```
|
95
|
+
|
77
96
|
### Client
|
78
97
|
|
79
98
|
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.
|
@@ -115,6 +134,7 @@ client.users(1).delete! #DELETE requst to /users
|
|
115
134
|
require 'rapidash'
|
116
135
|
|
117
136
|
class Me < Rapidash::Base
|
137
|
+
url "me"
|
118
138
|
end
|
119
139
|
|
120
140
|
class Facebook < Rapidash::Client
|
@@ -136,9 +156,9 @@ p client.me!.first_name #Gary
|
|
136
156
|
```ruby
|
137
157
|
require 'rapidash'
|
138
158
|
|
139
|
-
class
|
159
|
+
class Repo < Rapidash::Base
|
140
160
|
|
141
|
-
class
|
161
|
+
class User < Rapidash::Base
|
142
162
|
resource :repos
|
143
163
|
end
|
144
164
|
|
@@ -153,13 +173,30 @@ p client.users!("Gazler").name #Gary Rennie
|
|
153
173
|
p client.users("Gazler").repos![0].name #Githug
|
154
174
|
```
|
155
175
|
|
176
|
+
### HTTP Authentication
|
177
|
+
|
178
|
+
```ruby
|
179
|
+
require 'rapidash'
|
180
|
+
|
181
|
+
class Client < Rapidash::Client
|
182
|
+
method :http
|
183
|
+
site "your site"
|
184
|
+
end
|
185
|
+
|
186
|
+
client = Client.new({
|
187
|
+
:login => "your login",
|
188
|
+
:password => "your password",
|
189
|
+
})
|
190
|
+
```
|
191
|
+
|
156
192
|
## Contributing
|
157
193
|
|
158
194
|
1. Fork it
|
159
195
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
160
196
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
161
|
-
4.
|
162
|
-
5.
|
197
|
+
4. Write your tests, start and check coverage: open file coverage/index.html in your browser. Must be 100.0% covered
|
198
|
+
5. Push to the branch (`git push origin my-new-feature`)
|
199
|
+
6. Create new Pull Request (into the development branch)
|
163
200
|
|
164
201
|
## Credits
|
165
202
|
|
data/examples/github.rb
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
require 'rapidash'
|
2
2
|
|
3
|
-
class
|
3
|
+
class Repo < Rapidash::Base
|
4
4
|
def repo!(owner, repo)
|
5
5
|
self.url += "/#{owner}/#{repo}"
|
6
6
|
call!
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
-
class
|
10
|
+
class User < Rapidash::Base
|
11
11
|
resource :repos
|
12
12
|
end
|
13
13
|
|
14
|
-
class
|
14
|
+
class Emoji < Rapidash::Base
|
15
15
|
end
|
16
16
|
|
17
|
-
class
|
17
|
+
class Event < Rapidash::Base
|
18
18
|
end
|
19
19
|
|
20
|
-
class
|
20
|
+
class Gist < Rapidash::Base
|
21
21
|
|
22
22
|
def public!
|
23
23
|
self.url += "/public"
|
@@ -26,7 +26,7 @@ class Gists < Rapidash::Base
|
|
26
26
|
|
27
27
|
end
|
28
28
|
|
29
|
-
class
|
29
|
+
class Organisation < Rapidash::Base
|
30
30
|
url "orgs"
|
31
31
|
end
|
32
32
|
|
data/lib/rapidash.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
+
#Required for pluralization and camelcasing
|
2
|
+
require "active_support/core_ext/string"
|
3
|
+
|
1
4
|
require "rapidash/version"
|
2
5
|
|
3
6
|
require "rapidash/errors"
|
4
7
|
|
5
8
|
require "rapidash/response"
|
6
9
|
|
7
|
-
require "rapidash/clientable"
|
8
10
|
require "rapidash/resourceable"
|
9
11
|
require "rapidash/client"
|
10
12
|
|
data/lib/rapidash/base.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
module Rapidash
|
2
2
|
class Base
|
3
|
-
|
4
3
|
include Urlable
|
5
4
|
include Resourceable
|
6
5
|
|
@@ -24,7 +23,7 @@ module Rapidash
|
|
24
23
|
|
25
24
|
@options ||= {}
|
26
25
|
@options.merge!(options || {})
|
27
|
-
@url = "#{base_url}#{
|
26
|
+
@url = "#{base_url}#{resource_url}"
|
28
27
|
@url += "/#{@id}" if @id
|
29
28
|
end
|
30
29
|
|
@@ -55,21 +54,24 @@ module Rapidash
|
|
55
54
|
client.send(method, url, options)
|
56
55
|
end
|
57
56
|
|
57
|
+
|
58
58
|
private
|
59
59
|
|
60
60
|
def set_body!(params)
|
61
61
|
if self.class.root_element
|
62
|
-
options[:body] = {self.class.root_element => params}
|
62
|
+
options[:body] = {self.class.root_element => params}
|
63
63
|
else
|
64
|
-
options[:body] = params
|
64
|
+
options[:body] = params
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
68
|
def base_url
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
69
|
+
old_url = self.options[:previous_url]
|
70
|
+
old_url ? "#{old_url}/" : ""
|
71
|
+
end
|
72
|
+
|
73
|
+
def resource_url
|
74
|
+
self.options[:url] || self.class.to_s.split("::")[-1].downcase.pluralize
|
73
75
|
end
|
74
76
|
end
|
75
77
|
end
|
data/lib/rapidash/client.rb
CHANGED
@@ -1,12 +1,65 @@
|
|
1
1
|
module Rapidash
|
2
2
|
class Client
|
3
|
-
include Clientable
|
4
3
|
include Resourceable
|
5
4
|
|
5
|
+
attr_accessor :extension
|
6
|
+
|
6
7
|
def initialize
|
7
8
|
raise ConfigurationError.new "Missing Method, define using `method` on your client"
|
8
9
|
end
|
9
10
|
|
11
|
+
class << self
|
12
|
+
attr_accessor :patch, :raise_error
|
13
|
+
|
14
|
+
def method(method)
|
15
|
+
case method
|
16
|
+
when :http then include HTTPClient
|
17
|
+
when :oauth then include OAuthClient
|
18
|
+
when :test then include TestClient
|
19
|
+
else
|
20
|
+
raise ConfigurationError.new "Invalid API Authentication Method"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def use_patch
|
25
|
+
@patch = true
|
26
|
+
end
|
27
|
+
|
28
|
+
def extension(extension = nil)
|
29
|
+
@extension ||= extension
|
30
|
+
end
|
31
|
+
|
32
|
+
def site(site = nil)
|
33
|
+
@site ||= site
|
34
|
+
end
|
35
|
+
|
36
|
+
def raise_errors
|
37
|
+
@raise_error = true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Instance methods
|
42
|
+
|
43
|
+
def site
|
44
|
+
return @site if @site
|
45
|
+
self.class.respond_to?(:site) && self.class.site
|
46
|
+
end
|
47
|
+
|
48
|
+
def site=(value)
|
49
|
+
@site = value
|
50
|
+
@connection = nil
|
51
|
+
end
|
52
|
+
|
53
|
+
def normalize_url(url)
|
54
|
+
if extension
|
55
|
+
"#{url}.#{extension}"
|
56
|
+
elsif self.class.respond_to?(:extension) && self.class.extension
|
57
|
+
"#{url}.#{self.class.extension}"
|
58
|
+
else
|
59
|
+
url
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
10
63
|
def get(url, options = {})
|
11
64
|
request(:get, url, options)
|
12
65
|
end
|
@@ -26,6 +79,5 @@ module Rapidash
|
|
26
79
|
def delete(url, options = {})
|
27
80
|
request(:delete, url, options)
|
28
81
|
end
|
29
|
-
|
30
82
|
end
|
31
83
|
end
|
data/lib/rapidash/http_client.rb
CHANGED
@@ -2,37 +2,32 @@ require 'faraday'
|
|
2
2
|
|
3
3
|
module Rapidash
|
4
4
|
module HTTPClient
|
5
|
-
|
6
|
-
def self.included(base)
|
7
|
-
base.extend(ClassMethods)
|
8
|
-
end
|
9
|
-
|
10
|
-
attr_accessor :extension, :site
|
5
|
+
attr_accessor :login, :password
|
11
6
|
attr_writer :connection
|
12
7
|
|
13
|
-
def initialize
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
@site = site
|
18
|
-
@connection = nil
|
8
|
+
def initialize(options = {})
|
9
|
+
[:login, :password].each do |key|
|
10
|
+
self.send("#{key.to_s}=".to_sym, options[key])
|
11
|
+
end
|
19
12
|
end
|
20
13
|
|
21
14
|
def connection
|
22
|
-
|
15
|
+
raise ConfigurationError.new "Site is required" unless site
|
16
|
+
@connection ||= Faraday.new(site)
|
23
17
|
end
|
24
18
|
|
25
19
|
def request(verb, url, options = {})
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
url = "#{url}.#{(self.class.url_extension)}"
|
20
|
+
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
|
30
23
|
end
|
31
|
-
url = connection.build_url(url, options[:params]).to_s
|
32
|
-
response = connection.run_request(verb, url, options[:body], options[:headers])
|
33
24
|
|
25
|
+
process_response(response, verb, options)
|
26
|
+
end
|
27
|
+
|
28
|
+
def process_response(response, verb, options)
|
34
29
|
# "foo"[0] does not work in 1.8.7, "foo"[0,1] is required
|
35
|
-
case response.status.to_s[0,1]
|
30
|
+
case response.status.to_s[0, 1]
|
36
31
|
when "5", "4"
|
37
32
|
error = ResponseError.new(response)
|
38
33
|
raise error if self.class.respond_to?(:raise_error) && self.class.raise_error
|
@@ -44,15 +39,5 @@ module Rapidash
|
|
44
39
|
return Response.new(response)
|
45
40
|
end
|
46
41
|
end
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
module ClassMethods
|
51
|
-
attr_accessor :site_url
|
52
|
-
|
53
|
-
def site(site)
|
54
|
-
@site_url = site
|
55
|
-
end
|
56
|
-
end
|
57
42
|
end
|
58
43
|
end
|
@@ -3,29 +3,29 @@ require 'hashie'
|
|
3
3
|
|
4
4
|
module Rapidash
|
5
5
|
module OAuthClient
|
6
|
-
|
7
|
-
attr_accessor :secret, :uid, :access_token, :site, :extension
|
6
|
+
attr_accessor :secret, :uid, :access_token, :site
|
8
7
|
|
9
8
|
def initialize(options)
|
10
9
|
[:uid, :secret, :site].each do |key|
|
11
10
|
if options[key]
|
12
11
|
self.send("#{key.to_s}=".to_sym, options[key])
|
13
12
|
else
|
14
|
-
|
13
|
+
unless self.class.respond_to?(key) && send(key)
|
14
|
+
raise ConfigurationError.new "Missing #{key} value"
|
15
|
+
end
|
15
16
|
end
|
16
17
|
end
|
18
|
+
|
17
19
|
self.access_token = options[:access_token] if options[:access_token]
|
18
20
|
end
|
19
21
|
|
20
22
|
def request(verb, url, options = {})
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
url = "#{url}.#{(self.class.url_extension)}"
|
25
|
-
end
|
26
|
-
options[:raise_errors] = self.class.respond_to?(:raise_error) && self.class.raise_error
|
23
|
+
url = normalize_url(url)
|
24
|
+
options[:body] = options[:body].to_json if options[:body]
|
25
|
+
options[:raise_errors] = self.class.respond_to?(:raise_error) && self.class.raise_error
|
27
26
|
response = oauth_access_token.send(verb.to_sym, "#{site}/#{url}", options)
|
28
|
-
|
27
|
+
|
28
|
+
Response.new(response)
|
29
29
|
end
|
30
30
|
|
31
31
|
def access_token_from_code(code, url)
|
@@ -1,30 +1,50 @@
|
|
1
1
|
module Rapidash
|
2
2
|
module Resourceable
|
3
|
-
|
4
3
|
def self.included(base)
|
5
4
|
base.extend ClassMethods
|
6
5
|
end
|
7
6
|
|
8
|
-
|
7
|
+
def resource(name, id = nil, options = {})
|
8
|
+
options[:url] ||= name
|
9
|
+
if self.respond_to?(:url)
|
10
|
+
options = {:previous_url => self.url}.merge!(options)
|
11
|
+
end
|
12
|
+
client = self
|
13
|
+
client = self.client if self.respond_to?(:client)
|
14
|
+
Rapidash::Base.new(client, id, options)
|
15
|
+
end
|
9
16
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
mod = Kernel
|
14
|
-
else
|
15
|
-
mod = Kernel.const_get(mod.join("::"))
|
16
|
-
end
|
17
|
+
def resource!(*args)
|
18
|
+
self.resource(*args).call!
|
19
|
+
end
|
17
20
|
|
18
21
|
|
22
|
+
module ClassMethods
|
23
|
+
def resource(*names)
|
24
|
+
options = names.extract_options!
|
25
|
+
|
26
|
+
mod = self.to_s.split("::")[0...-1]
|
27
|
+
mod = mod.empty? ? Object : Object.const_get(mod.join("::"))
|
19
28
|
|
20
29
|
names.each do |name|
|
21
|
-
|
30
|
+
if options[:class_name]
|
31
|
+
class_name = options[:class_name]
|
32
|
+
else
|
33
|
+
class_name = name.to_s.camelcase.singularize
|
34
|
+
end
|
35
|
+
|
36
|
+
begin
|
37
|
+
klass = "#{mod}::#{class_name}".constantize
|
38
|
+
rescue NameError
|
39
|
+
Kernel.warn "[DEPRECATED] - RAPIDASH WARNING using #{class_name.pluralize} instead of #{class_name.singularize} - please either use `#{class_name.singularize}` or set the class name with `resource #{name}, :class_name => #{class_name.pluralize}` implicit plural naming will be deprecated in Rapidash 1.0"
|
40
|
+
klass = "#{mod}::#{class_name}".pluralize.constantize
|
41
|
+
end
|
22
42
|
|
23
43
|
define_method(name) do |*args|
|
24
44
|
if self.respond_to?(:url)
|
25
45
|
options = {:previous_url => self.url}
|
26
|
-
if args[args.length].is_a?(Hash)
|
27
|
-
args[args.length].merge!(options)
|
46
|
+
if args[args.length - 1].is_a?(Hash)
|
47
|
+
args[args.length - 1].merge!(options)
|
28
48
|
else
|
29
49
|
args << options
|
30
50
|
end
|
@@ -39,8 +59,6 @@ module Rapidash
|
|
39
59
|
end
|
40
60
|
end
|
41
61
|
end
|
42
|
-
|
43
62
|
end
|
44
|
-
|
45
63
|
end
|
46
64
|
end
|