octoplex 0.0.2 → 0.0.3
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.
- data/Gemfile +1 -0
- data/README.md +60 -0
- data/lib/octoplex/client/repository.rb +0 -9
- data/lib/octoplex/client/root.rb +56 -10
- data/lib/octoplex/client/user.rb +4 -21
- data/lib/octoplex/connection.rb +48 -8
- data/lib/octoplex/version.rb +1 -1
- data/railsonfire.yml +13 -0
- data/spec/lib/octoplex/connection_spec.rb +27 -2
- data/spec/lib/octoplex_spec.rb +1 -1
- metadata +19 -18
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -56,6 +56,66 @@ Octoplex.rate_limit #=> 5000
|
|
56
56
|
Octoplex.rate_limit_remaining #=> 4999
|
57
57
|
```
|
58
58
|
|
59
|
+
There are times when you may want to run multiple instances of the `Octoplex::Client` side by side
|
60
|
+
with different tokens.
|
61
|
+
|
62
|
+
The recommended approach for this is to not use the global `Octoplex` object, rather instantiate `Octoplex::Client`
|
63
|
+
individually.
|
64
|
+
|
65
|
+
``` ruby
|
66
|
+
client = Octoplex::Client.new(:token => "AUTH_TOKEN")
|
67
|
+
client.get('/user')
|
68
|
+
```
|
69
|
+
|
70
|
+
### Configuration
|
71
|
+
|
72
|
+
You can specify a number of connection options before making your first request, but remember, the connection object is cached so you will
|
73
|
+
need to call `Octoplex.discard_client!` if you want to change anything.
|
74
|
+
|
75
|
+
Available options:
|
76
|
+
``` ruby
|
77
|
+
{
|
78
|
+
:token => YOU OAUTH AUTHENTICATION TOKEN, Default: nil,
|
79
|
+
:per_page => THE NUMBER OF ITEMS TO REQUEST AT ONCE, Default: 100,
|
80
|
+
:enable_caching, ENABLE REQUEST CACHING, Default: true
|
81
|
+
}
|
82
|
+
```
|
83
|
+
Pass these to `Octoplex.client(options)`
|
84
|
+
|
85
|
+
### Repositories
|
86
|
+
|
87
|
+
Here is a quick rundown on using `Octoplex` to interact with Repositories.
|
88
|
+
|
89
|
+
**List all for a user**
|
90
|
+
``` ruby
|
91
|
+
Octoplex.repos('ivanvanderbyl')
|
92
|
+
# or, take the object orientated approach
|
93
|
+
Octoplex.users('testpilot').repos
|
94
|
+
```
|
95
|
+
|
96
|
+
**List all for the current user**
|
97
|
+
``` ruby
|
98
|
+
Octoplex.repos
|
99
|
+
# or
|
100
|
+
Octoplex.user.repos
|
101
|
+
```
|
102
|
+
|
103
|
+
**Fetch a specific repo**
|
104
|
+
``` ruby
|
105
|
+
Octoplex.repo('ivanvanderbyl/cloudist')
|
106
|
+
# or
|
107
|
+
Octoplex.repo('ivanvanderbyl', 'cloudist')
|
108
|
+
```
|
109
|
+
|
110
|
+
**List all for an Organisation**
|
111
|
+
``` ruby
|
112
|
+
Octoplex.orgs('testpilot').repos
|
113
|
+
# or
|
114
|
+
Octoplex.repos('testpilot')
|
115
|
+
```
|
116
|
+
|
117
|
+
|
118
|
+
|
59
119
|
### Language note
|
60
120
|
|
61
121
|
This library is written in International English, so if you're wondering why we've swapped your Zs for S, and added a U to colour – get a dictionary.
|
data/lib/octoplex/client/root.rb
CHANGED
@@ -2,17 +2,28 @@ module Octoplex
|
|
2
2
|
class Client
|
3
3
|
module Root
|
4
4
|
|
5
|
+
# Get a single user
|
6
|
+
#
|
7
|
+
# API: GET /user
|
8
|
+
# GET /users/:login
|
9
|
+
def user(login=nil)
|
10
|
+
if login
|
11
|
+
users(login)
|
12
|
+
else
|
13
|
+
Octoplex::Client::User.new(self, get("/user"))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
5
17
|
# GET /users/:user
|
6
|
-
# GET /users/:user/repos
|
7
18
|
def users(login)
|
8
|
-
|
19
|
+
Octoplex::Client::User.new(self, get("/users/#{login}"))
|
9
20
|
end
|
10
21
|
|
11
|
-
# GET /user
|
12
|
-
# GET /user/repos
|
13
|
-
def user
|
14
|
-
|
15
|
-
end
|
22
|
+
# # GET /user
|
23
|
+
# # GET /user/repos
|
24
|
+
# def user
|
25
|
+
# @user ||= Octoplex::API::User.current
|
26
|
+
# end
|
16
27
|
|
17
28
|
# GET /orgs/:org/repos
|
18
29
|
def orgs(login)
|
@@ -22,16 +33,51 @@ module Octoplex
|
|
22
33
|
alias_method :organisations, :orgs
|
23
34
|
alias_method :organizations, :orgs
|
24
35
|
|
25
|
-
|
36
|
+
|
26
37
|
# GET /repos/:user/:repo/contributors
|
27
38
|
# GET /repos/:user/:repo/languages
|
28
39
|
# GET /repos/:user/:repo/teams
|
29
40
|
# GET /repos/:user/:repo/branches
|
30
41
|
|
31
|
-
|
32
|
-
|
42
|
+
# GET /repos/:user/:repo
|
43
|
+
#
|
44
|
+
# Accepts either a user name and repo name as 2 arguments or one.
|
45
|
+
# Example:
|
46
|
+
# Octoplex.repo('ivanvanderbyl/cloudist')
|
47
|
+
# Octoplex.repo('ivanvanderbyl', 'cloudist')
|
48
|
+
def repos(*user_and_repo)
|
49
|
+
if user_and_repo.size == 2
|
50
|
+
# We've been supplied two arguments
|
51
|
+
user = user_and_repo[0]
|
52
|
+
repo = user_and_repo[1]
|
53
|
+
elsif user_and_repo.first.is_a?(String) && !user_and_repo.first.index('/').nil?
|
54
|
+
# We've been supplied a string like "ivanvanderbyl/cloudist"
|
55
|
+
user, repo = user_and_repo[0].split('/', 2)
|
56
|
+
elsif user_and_repo.size == 1
|
57
|
+
# We've been supplied one argument, probably a username
|
58
|
+
user = user_and_repo[0]
|
59
|
+
repo = nil
|
60
|
+
else
|
61
|
+
raise ArgumentError, "Unknown arguments: #{user_and_repo.split(', ')}"
|
62
|
+
end
|
63
|
+
if repo.nil?
|
64
|
+
path = "/users/#{user}/repos"
|
65
|
+
else
|
66
|
+
path = "/repos/#{user}/#{repo}"
|
67
|
+
end
|
68
|
+
|
69
|
+
data = get(path)
|
70
|
+
if data.is_a?(Array)
|
71
|
+
data.map { |o| Octoplex::Client::Repository.new(self, o) }
|
72
|
+
else
|
73
|
+
Octoplex::Client::Repository.new(self, data)
|
74
|
+
end
|
33
75
|
end
|
34
76
|
|
77
|
+
alias_method :repo, :repos
|
78
|
+
alias_method :repositories, :repos
|
79
|
+
alias_method :repository, :repos
|
80
|
+
|
35
81
|
end
|
36
82
|
end
|
37
83
|
end
|
data/lib/octoplex/client/user.rb
CHANGED
@@ -1,27 +1,10 @@
|
|
1
1
|
module Octoplex
|
2
2
|
class Client
|
3
|
-
class
|
3
|
+
class User < Base
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
# def find(client, login)
|
9
|
-
# new(client.get("/users/#{login}"))
|
10
|
-
# end
|
11
|
-
#
|
12
|
-
# def current(client)
|
13
|
-
# new(client.get("/user"))
|
14
|
-
# end
|
15
|
-
# end
|
16
|
-
|
17
|
-
# GET /users/:user/[repos]
|
18
|
-
# def repos
|
19
|
-
# Octoplex::API::Repository.all
|
20
|
-
# # get("/user/#{login}/repos")
|
21
|
-
# end
|
22
|
-
|
23
|
-
def repos
|
24
|
-
Octoplex::API::Repository.new(login, self, get("/users/repos"))
|
5
|
+
# GET /repos/:user/:repo
|
6
|
+
def repos(repo)
|
7
|
+
Octoplex::Client::Repository.new(client, "/repos/#{login}/#{repo}")
|
25
8
|
end
|
26
9
|
|
27
10
|
end
|
data/lib/octoplex/connection.rb
CHANGED
@@ -6,17 +6,25 @@ require "faraday/response/raise_octoplex_error"
|
|
6
6
|
module Octoplex
|
7
7
|
class Connection
|
8
8
|
|
9
|
-
attr_reader :conn, :options, :token, :rate_limit, :rate_limit_remaining
|
9
|
+
attr_reader :conn, :options, :conn_options, :token, :rate_limit, :rate_limit_remaining
|
10
10
|
|
11
11
|
def initialize(options = {})
|
12
12
|
options ||= {}
|
13
13
|
|
14
14
|
@options = {
|
15
|
-
:
|
16
|
-
:
|
15
|
+
:per_page => 100,
|
16
|
+
:enable_caching => true,
|
17
|
+
:logging => false,
|
18
|
+
:token => nil
|
17
19
|
}.update(options)
|
18
20
|
|
19
|
-
@
|
21
|
+
@conn_options = {
|
22
|
+
:logging => @options.delete(:logging),
|
23
|
+
:access_token => @options.delete(:token),
|
24
|
+
:enable_caching => @options.delete(:enable_caching)
|
25
|
+
}
|
26
|
+
|
27
|
+
@token = @conn_options[:access_token]
|
20
28
|
@rate_limit = @rate_limit_remaining = 0
|
21
29
|
setup
|
22
30
|
end
|
@@ -24,7 +32,7 @@ module Octoplex
|
|
24
32
|
def setup
|
25
33
|
@conn = Faraday.new(:url => 'https://api.github.com') do |builder|
|
26
34
|
builder.use Faraday::Request::JSON
|
27
|
-
builder.use Faraday::Response::Logger
|
35
|
+
builder.use Faraday::Response::Logger if conn_options[:logging].eql?(true)
|
28
36
|
builder.use Faraday::Adapter::NetHttp
|
29
37
|
builder.use Faraday::Response::Hashr
|
30
38
|
builder.use Faraday::Response::RaiseOctoplexError
|
@@ -52,13 +60,46 @@ module Octoplex
|
|
52
60
|
request(path, :delete)
|
53
61
|
end
|
54
62
|
|
63
|
+
def cache(path, response)
|
64
|
+
if options[:enable_caching] == true
|
65
|
+
(@cache ||= {})[path.to_s] = response
|
66
|
+
end
|
67
|
+
response
|
68
|
+
end
|
69
|
+
|
70
|
+
def cached(path)
|
71
|
+
(@cache ||= {})[path.to_s]
|
72
|
+
end
|
73
|
+
|
74
|
+
def is_cached?(path)
|
75
|
+
(@cache ||= {}).has_key?(path)
|
76
|
+
end
|
77
|
+
|
78
|
+
def clear_cache
|
79
|
+
@cache = {}
|
80
|
+
end
|
81
|
+
|
82
|
+
def cache_size
|
83
|
+
(@cache ||= {}).keys.size
|
84
|
+
end
|
85
|
+
|
55
86
|
private
|
56
87
|
|
57
88
|
def request(path, method = :get, body = nil)
|
89
|
+
if is_cached?(path)
|
90
|
+
return cached(path)
|
91
|
+
end
|
92
|
+
|
93
|
+
data = make_request(path, method, body)
|
94
|
+
cache(path, data)
|
95
|
+
end
|
96
|
+
|
97
|
+
def make_request(path, method = :get, body = nil)
|
58
98
|
response = conn.send(method) do |req|
|
59
|
-
req.url(path
|
99
|
+
req.url(path)
|
60
100
|
req.body = body unless body.nil?
|
61
|
-
req.params
|
101
|
+
req.params.merge!(authentication_param) if self.token.is_a?(String)
|
102
|
+
req.params['per_page'] = self.options[:per_page] if (self.options.has_key?(:per_page) && method == :get)
|
62
103
|
end
|
63
104
|
|
64
105
|
if response.env[:response_headers].has_key?('x-ratelimit-limit')
|
@@ -70,5 +111,4 @@ module Octoplex
|
|
70
111
|
end
|
71
112
|
|
72
113
|
end
|
73
|
-
|
74
114
|
end
|
data/lib/octoplex/version.rb
CHANGED
data/railsonfire.yml
ADDED
@@ -24,6 +24,7 @@ describe Octoplex::Connection do
|
|
24
24
|
test = Faraday.new do |builder|
|
25
25
|
builder.adapter :test, c do |stub|
|
26
26
|
stub.get('/user/keys') {[ 200, {}, user_keys_payload ]}
|
27
|
+
stub.get('/users/ivan/cloudist') {[ 200, {}, JSON.dump({:login => 'ivan'})]}
|
27
28
|
stub.post('/user/keys/123') {[ 200, {}, JSON.dump(user_key) ]}
|
28
29
|
end
|
29
30
|
|
@@ -44,7 +45,31 @@ describe Octoplex::Connection do
|
|
44
45
|
end
|
45
46
|
|
46
47
|
it "should return accept token as first argument" do
|
47
|
-
conn = Octoplex::Connection.new('1234')
|
48
|
+
conn = Octoplex::Connection.new(:token => '1234')
|
48
49
|
conn.token.should == '1234'
|
49
50
|
end
|
50
|
-
|
51
|
+
|
52
|
+
describe "caching" do
|
53
|
+
it "should cache each request and it's response" do
|
54
|
+
conn = Octoplex::Connection.new(:token => '1234')
|
55
|
+
conn.expects(:cached).with('/users/ivan/cloudist').returns({'login' => 'ivan'}).once
|
56
|
+
|
57
|
+
conn.get('/users/ivan/cloudist').should == {'login' => 'ivan'}
|
58
|
+
# This second request should hit cache
|
59
|
+
# and avoid caching the resuult
|
60
|
+
conn.expects(:cache).with('/users/ivan/cloudist', {'login' => 'ivan'}).never
|
61
|
+
conn.get('/users/ivan/cloudist').should == {'login' => 'ivan'}
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should not cache response if caching is disabled" do
|
65
|
+
conn = Octoplex::Connection.new(:token => '1234', :enable_caching => false)
|
66
|
+
conn.expects(:cached).with('/users/ivan/cloudist').never
|
67
|
+
|
68
|
+
conn.get('/users/ivan/cloudist').should == {'login' => 'ivan'}
|
69
|
+
# This second request should hit cache
|
70
|
+
# and avoid caching the resuult
|
71
|
+
conn.expects(:cache).with('/users/ivan/cloudist', {'login' => 'ivan'}).returns({'login' => 'ivan'}).once
|
72
|
+
conn.get('/users/ivan/cloudist').should == {'login' => 'ivan'}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/spec/lib/octoplex_spec.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: octoplex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
12
|
+
date: 2011-11-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &70217171120640 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70217171120640
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: mocha
|
27
|
-
requirement: &
|
27
|
+
requirement: &70217171120220 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70217171120220
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: awesome_print
|
38
|
-
requirement: &
|
38
|
+
requirement: &70217171119800 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70217171119800
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: faraday
|
49
|
-
requirement: &
|
49
|
+
requirement: &70217171119380 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70217171119380
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: multi_json
|
60
|
-
requirement: &
|
60
|
+
requirement: &70217171118960 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70217171118960
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: yajl-ruby
|
71
|
-
requirement: &
|
71
|
+
requirement: &70217154190020 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70217154190020
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: hashr
|
82
|
-
requirement: &
|
82
|
+
requirement: &70217154189600 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :runtime
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70217154189600
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: link_header
|
93
|
-
requirement: &
|
93
|
+
requirement: &70217154189100 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - =
|
@@ -98,7 +98,7 @@ dependencies:
|
|
98
98
|
version: 0.0.5
|
99
99
|
type: :runtime
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70217154189100
|
102
102
|
description: A lightweight wrapper around the Github v3 API
|
103
103
|
email:
|
104
104
|
- ivanvanderbyl@me.com
|
@@ -125,6 +125,7 @@ files:
|
|
125
125
|
- lib/octoplex/errors.rb
|
126
126
|
- lib/octoplex/version.rb
|
127
127
|
- octoplex.gemspec
|
128
|
+
- railsonfire.yml
|
128
129
|
- spec/lib/octoplex/api/user_spec.rb
|
129
130
|
- spec/lib/octoplex/client_spec.rb
|
130
131
|
- spec/lib/octoplex/connection_spec.rb
|