octoplex 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,4 +1,5 @@
1
1
  source "http://rubygems.org"
2
2
 
3
+ gem 'rake', '~> 0.9.2'
3
4
  # Specify your gem's dependencies in octoplex.gemspec
4
5
  gemspec
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.
@@ -2,15 +2,6 @@ module Octoplex
2
2
  class Client
3
3
  class Repository < Base
4
4
 
5
- attr_reader :owner
6
-
7
- def initialize(owner, client, data)
8
- super(client, data)
9
- @owner = owner
10
- end
11
-
12
-
13
-
14
5
  # GET /repos/:user/:repo
15
6
 
16
7
  # GET /repos/:user/:repo/contributors
@@ -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
- (@users ||= {})[login] ||= Octoplex::API::User.new(self, get("/users/#{login}"))
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
- @user ||= Octoplex::API::User.current
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
- # GET /repos/:user/:repo
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
- def repos(user, repo)
32
- (@repos ||= {})[user] ||= Octoplex::API::Repository.new(user, self, get("/repos/#{user}"))
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
@@ -1,27 +1,10 @@
1
1
  module Octoplex
2
2
  class Client
3
- class Users < Base
3
+ class User < Base
4
4
 
5
-
6
-
7
- # class << self
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
@@ -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
- :token => nil,
16
- :per_page => 100
15
+ :per_page => 100,
16
+ :enable_caching => true,
17
+ :logging => false,
18
+ :token => nil
17
19
  }.update(options)
18
20
 
19
- @token = options.delete(:token)
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, options)
99
+ req.url(path)
60
100
  req.body = body unless body.nil?
61
- req.params['access_token'] = self.token if self.token.is_a?(String)
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
@@ -1,3 +1,3 @@
1
1
  module Octoplex
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -0,0 +1,13 @@
1
+ ---
2
+ :test:
3
+ :commands:
4
+ - gem install bundler --no-ri --no-rdoc
5
+ - bundle install --without development production
6
+ - bundle exec rake spec
7
+ :deploy:
8
+ :branch: master
9
+ :commands: []
10
+ :ruby_versions:
11
+ - 1.9.2
12
+ - 1.9.3.rc1
13
+ - 1.8.7
@@ -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
- end
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
@@ -8,4 +8,4 @@ describe Octoplex do
8
8
  Octoplex.instance_variable_get("@client").should be_a Octoplex::Client
9
9
  end
10
10
  end
11
- end
11
+ end
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.2
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-10-05 00:00:00.000000000 Z
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: &70219242559780 !ruby/object:Gem::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: *70219242559780
24
+ version_requirements: *70217171120640
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: mocha
27
- requirement: &70219242555300 !ruby/object:Gem::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: *70219242555300
35
+ version_requirements: *70217171120220
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: awesome_print
38
- requirement: &70219242551960 !ruby/object:Gem::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: *70219242551960
46
+ version_requirements: *70217171119800
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: faraday
49
- requirement: &70219242548380 !ruby/object:Gem::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: *70219242548380
57
+ version_requirements: *70217171119380
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: multi_json
60
- requirement: &70219242545120 !ruby/object:Gem::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: *70219242545120
68
+ version_requirements: *70217171118960
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: yajl-ruby
71
- requirement: &70219242543700 !ruby/object:Gem::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: *70219242543700
79
+ version_requirements: *70217154190020
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: hashr
82
- requirement: &70219242542420 !ruby/object:Gem::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: *70219242542420
90
+ version_requirements: *70217154189600
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: link_header
93
- requirement: &70219242539740 !ruby/object:Gem::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: *70219242539740
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