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 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