githu3 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/README.md +179 -0
  2. data/bin/githu3 +7 -0
  3. data/lib/faraday/response/parse_json.rb +22 -0
  4. data/lib/githu3/cache/disk.rb +43 -0
  5. data/lib/githu3/cache/redis.rb +35 -0
  6. data/lib/githu3/cache.rb +8 -0
  7. data/lib/githu3/cli.rb +25 -0
  8. data/lib/githu3/client.rb +46 -30
  9. data/lib/githu3/comment.rb +15 -0
  10. data/lib/githu3/commit.rb +13 -0
  11. data/lib/githu3/connection.rb +47 -0
  12. data/lib/githu3/core_ext/hash.rb +18 -0
  13. data/lib/githu3/download.rb +4 -0
  14. data/lib/githu3/event.rb +6 -0
  15. data/lib/githu3/git_commit.rb +5 -0
  16. data/lib/githu3/issue.rb +10 -1
  17. data/lib/githu3/org.rb +1 -1
  18. data/lib/githu3/pull.rb +9 -0
  19. data/lib/githu3/ref.rb +9 -0
  20. data/lib/githu3/relations.rb +22 -2
  21. data/lib/githu3/repo.rb +14 -4
  22. data/lib/githu3/resource.rb +19 -4
  23. data/lib/githu3/resource_collection.rb +26 -9
  24. data/lib/githu3/store.rb +2 -2
  25. data/lib/githu3/team.rb +4 -0
  26. data/lib/githu3/tree.rb +4 -0
  27. data/lib/githu3/user.rb +5 -0
  28. data/lib/githu3/version.rb +1 -1
  29. data/lib/githu3.rb +23 -1
  30. metadata +94 -119
  31. data/.autotest +0 -3
  32. data/.document +0 -5
  33. data/.gitignore +0 -22
  34. data/.rspec +0 -4
  35. data/.travis.yml +0 -6
  36. data/Gemfile +0 -16
  37. data/Rakefile +0 -16
  38. data/githu3.gemspec +0 -34
  39. data/spec/fixtures/all_repos.json +0 -54
  40. data/spec/fixtures/error.json +0 -1
  41. data/spec/fixtures/issues/comments.json +0 -41
  42. data/spec/fixtures/issues/event.json +0 -12
  43. data/spec/fixtures/issues/events.json +0 -14
  44. data/spec/fixtures/me.json +0 -31
  45. data/spec/fixtures/orgs/github.json +0 -18
  46. data/spec/fixtures/orgs/rails.json +0 -18
  47. data/spec/fixtures/orgs.json +0 -14
  48. data/spec/fixtures/public_repos.json +0 -132
  49. data/spec/fixtures/repos/branches.json +0 -23
  50. data/spec/fixtures/repos/contributors.json +0 -58
  51. data/spec/fixtures/repos/faraday.json +0 -31
  52. data/spec/fixtures/repos/issue.json +0 -53
  53. data/spec/fixtures/repos/issues.json +0 -55
  54. data/spec/fixtures/repos/label.json +0 -5
  55. data/spec/fixtures/repos/labels.json +0 -7
  56. data/spec/fixtures/repos/milestone.json +0 -17
  57. data/spec/fixtures/repos/milestones.json +0 -19
  58. data/spec/fixtures/repos/tags.json +0 -164
  59. data/spec/fixtures/repos/teams.json +0 -17
  60. data/spec/fixtures/teams/1.json +0 -8
  61. data/spec/fixtures/teams/members.json +0 -8
  62. data/spec/fixtures/teams/repos.json +0 -28
  63. data/spec/fixtures/users/followers.json +0 -80
  64. data/spec/fixtures/users/following.json +0 -182
  65. data/spec/fixtures/users/orgs.json +0 -8
  66. data/spec/fixtures/users/repos.json +0 -132
  67. data/spec/fixtures/users/sbellity.json +0 -20
  68. data/spec/githu3/client_spec.rb +0 -66
  69. data/spec/githu3/error_spec.rb +0 -0
  70. data/spec/githu3/issue_spec.rb +0 -54
  71. data/spec/githu3/org_spec.rb +0 -79
  72. data/spec/githu3/repo_spec.rb +0 -100
  73. data/spec/githu3/resource_collection_spec.rb +0 -64
  74. data/spec/githu3/team_spec.rb +0 -47
  75. data/spec/githu3/user_spec.rb +0 -47
  76. data/spec/githu3_spec.rb +0 -7
  77. data/spec/helper.rb +0 -21
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # githu3 [![Build Status](http://travis-ci.org/sbellity/githu3.png)](http://travis-ci.org/sbellity/githu3)
2
2
 
3
+ githu3 is a ruby wrapper for github's v3 api.
4
+
3
5
 
4
6
  ## Installation
5
7
 
@@ -7,7 +9,184 @@
7
9
 
8
10
  ## Usage
9
11
 
12
+ ### Authentication
13
+
14
+ There are two ways to authenticate
15
+
16
+ Basic Authentication:
17
+
18
+ client = Githu3::Client.new('username', 'password')
19
+
20
+ OAuth2 Token (send in a header):
21
+
22
+ client = Githu3::Client.new('myawesomelyverylongoauth2token')
23
+
24
+ Or you can use the lib as an un-authenticated client to access only public Github resources...
10
25
 
26
+ client = Githu3::Client.new
27
+
28
+ ### Getting the basics
29
+
30
+ The Githu3::Client instance can directly access github's top-level resources : orgs, repos, teams and users
31
+
32
+ to get them :
33
+
34
+ c = Githu3::Client.new
35
+
36
+ # Org
37
+ rails_org = c.org 'rails' # -> 'rails' organization wrapped in a Gihu3::Org object
38
+
39
+ # Repo
40
+ rails_repo = c.repo 'rails/rails' # -> That's Rails !
41
+
42
+ # User
43
+ sbellity = c.user 'sbellity' # -> That's me !
44
+
45
+ # Team
46
+ a_team = c.team 123 # -> well... team number '123' if you have access to it
47
+
48
+
49
+ ### Getting your stuff
50
+
51
+ When authenticated, your Githu3::Client instance can give you direct access to your top-level stuff...
52
+
53
+ me = Githu3::Client.new 'myawesomelyverylongoauth2token'
54
+
55
+ # Orgs
56
+ # returns a paginable Githu3::ResourceCollection stuffed with YOUR organizations
57
+ # more on this Githu3::ResourceCollection thing later...
58
+ my_orgs = me.orgs
59
+
60
+ # Repos
61
+ my_repos = me.repos
62
+
63
+ # Me
64
+ me = me.me # -> well, you get the point...
65
+
66
+ # Followers
67
+ me.following # -> returns a list a the Githu3::User, that you follow
68
+ me.followers # -> returns a list a the Githu3::User, that follow you
69
+ me.following?("rails") # -> true if you follow 'rails', false otherwise
70
+
71
+
72
+ ### Getting deeper inside the API with Githu3::Resource Objects
73
+
74
+ All the calls to the API either return Githu3::Resource objects (ex. Githu3::User, Githu3::Repo, Githu3::Org...) et Githu3::ResourceCollection objects that wrap... Githu3::Resource objects
75
+
76
+ #### Attributes
77
+
78
+ All the member attributes are accessible directly via their names. If you try to access an attribute that does not exist... you'll get `nil`
79
+
80
+ Examples:
81
+
82
+ c = Githu3::Client.new
83
+
84
+ rails_org = c.org 'rails'
85
+ rails_org.login # -> 'rails'
86
+ rails_org.html_url # -> 'https://github.com/rails'
87
+ rails_org.public_repos # -> 44
88
+ rails_org.foo # -> nil
89
+
90
+
91
+ #### Relations
92
+
93
+ Relations between the Resources follow the nesting of the Github's REST Api. For example, you can get the list of an org's repos directly from the Githu3::Org object.
94
+
95
+ c = Githu3::Client.new
96
+ rails_org = c.org "rails"
97
+ rails_org.repos # -> the list of rails' repos
98
+
99
+ You can even do this !
100
+
101
+ rails_org.repos.first.issues # -> latest issues from rails' first repo
102
+
103
+
104
+ #### Embedding
105
+
106
+ Github often embeds objects inside others. For example, rails Repo has an owner object, that is a Githu3::User object... which let you do this:
107
+
108
+ rails_repo = c.repo "rails/rails"
109
+ rails_repo.owner # -> rails org wrapped in a Githu3::User object
110
+
111
+
112
+
113
+ ### Getting lots of stuff with Githu3::ResourceCollection Objects
114
+
115
+ #### Acts as Enumerable
116
+
117
+ Most results from the Api calls are collections of stuff. Those collections are wrapped in Githu3::ResourceCollection objects that primarily act as Arrays. Meaning that you can safely call the usual `length`, `first`, `last`, `each`, `map`, `select`... an so on... on them.
118
+
119
+ #### Pagination
120
+
121
+ _Warning !... this Pagination api is very alpha-ish... and very susceptible to change_
122
+
123
+ In fact, Github's api generally returns [paginated results](http://developer.github.com/v3/#pagination). Github::ResourceCollection have a pagination api built right in, that lets you do those kinds of stuff :
124
+
125
+ rails_repo = c.repo "rails/rails"
126
+ rails_issues = rails_repo.issues(:per_page => 10, :page => 4) # -> :per_page defaults to 30, :page defaults to 1
127
+
128
+ rails_issues.current_page # -> 4
129
+ rails_issues.length # -> 10
130
+
131
+ next_issues = rails_issues.fetch_next # -> next_issues is a plain Array here...
132
+ # new records are added to your original collection
133
+ rails_issues.current_page # -> 5
134
+ rails_issues.length # -> 20
135
+
136
+
137
+ #### Filtering & Sorting
138
+
139
+ Github Api provides filter options for most collection calls. To use a filter on your Githu3::ResourceCollection object, you can do
140
+
141
+ repo = c.repo "sbellity/githu3"
142
+ open_issues = repo.issues :state => "open"
143
+ bugs = repo.issues :tag => "bug"
144
+ my_issues = repo.issues :assignee => "sbellity"
145
+
146
+ # You can also combine and sort them
147
+ my_open_bugs = repo.issues :assignee => "sbellity",
148
+ :tag => "bug",
149
+ :state => "open",
150
+ :sort => "updated",
151
+ :direction => "desc"
152
+
153
+
154
+
155
+ ### Rate limiting
156
+
157
+ Your app may generate a LOT of requests to Github's API... By default, you are rate-limitted to 5000 requests per day. You can check anytime the status of your allowance via the method "rate_limit" on your Githu3::Client instance.
158
+
159
+ c = Githu3::Client.new
160
+ ...
161
+ c.rate_limit # -> {:limit=>"5000", :remaining=>"4969"}
162
+
163
+
164
+ ### Caching results
165
+
166
+ Githu3 provides a very basic cache mechanism to avoid making duplicate requests too often. Basically what it does is just record HTTP request results in a store with an expiration timeout and attempts to retrieve the results back from this store before hitting Github's servers. The different clients private data... should be safe, the request headers (that contain auth info) are used to generate the hash. 2 stores are provided by default : Redis and Disk.
167
+
168
+ To use them (these are the default options):
169
+
170
+ disk_cached_client = Githu3::Client.new('myawesomelyverylongoauth2token', :cache => :disk, :cache_options => {
171
+ :path => "/tmp/githu3",
172
+ :namespace => "cache", # or "myawesomelyverylongoauth2token" if you are paranoid...
173
+ :expiration => 120 # in seconds
174
+ })
175
+
176
+ redis_cached_client = Githu3::Client.new('myawesomelyverylongoauth2token', :cache => :redis, :cache_options => {
177
+ :host => "localhost", # defaults to localhost
178
+ :port => 6379 # defaults to 6379
179
+ :namespace => "githu3", # or "githu3:myawesomelyverylongoauth2token" if you are paranoid...
180
+ :expiration => 120 # in seconds
181
+ })
182
+
183
+
184
+ ## Limitations / Known issues
185
+
186
+ * The current version (0.1.x branch) only supports read (GET) operations on Github... support for CREATE / UPDATE operations should show up in the the 0.2.x branch.
187
+ * Github's api is still in beta, so this lib could break anytime if they change something, stay tuned for new versions and please report any issue on the project issue tracker.
188
+ * Some calls (ex. `c.repo('rails/rails').issues` -> 2 HTTP GET) make unnecessary calls to github, we will try to find a way to avoid this overhead in a future version.
189
+ * This lib is VERY young, please be kind and help me improve it
11
190
 
12
191
 
13
192
  ## Contributing to githu3
data/bin/githu3 ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.expand_path("../../lib", __FILE__)
4
+
5
+ require "githu3/cli"
6
+
7
+ Githu3::CLI.start
@@ -0,0 +1,22 @@
1
+ require 'faraday'
2
+
3
+ module Faraday
4
+ class Response::ParseJson < Response::Middleware
5
+ dependency 'multi_json'
6
+
7
+ def parse(body)
8
+ case body
9
+ when nil
10
+ nil
11
+ when ''
12
+ nil
13
+ when 'true'
14
+ true
15
+ when 'false'
16
+ false
17
+ else
18
+ ::MultiJson.decode(body)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,43 @@
1
+ require 'fileutils'
2
+
3
+ module Githu3
4
+ module Cache
5
+ class Disk
6
+ attr_reader :config, :store
7
+
8
+ DEFAULTS = {
9
+ :path => '/tmp/githu3',
10
+ :namespace => 'cache',
11
+ :expire => 120
12
+ } unless defined?(DEFAULTS)
13
+
14
+ def initialize opts={}
15
+ @config = DEFAULTS.merge(opts || {})
16
+ @path = ::File.expand_path(::File.join(@config[:path], @config[:namespace]))
17
+ FileUtils.mkdir_p @path
18
+ end
19
+
20
+ def get k
21
+ val = nil
22
+ file_path = ::File.join(@path, k)
23
+ if ::File.exists?(file_path)
24
+ if (Time.now - ::File.atime(file_path)) < @config[:expire]
25
+ val = Marshal.load(::File.read(file_path))
26
+ else
27
+ FileUtils.rm(file_path)
28
+ end
29
+ else
30
+ end
31
+ val
32
+ end
33
+
34
+ def set k, val, opts={}
35
+ file_path = ::File.join(@path, k)
36
+ f = open(file_path, 'wb')
37
+ f.write(Marshal.dump(val))
38
+ f.close
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,35 @@
1
+ require 'redis'
2
+ require 'redis/namespace'
3
+
4
+ module Githu3
5
+ module Cache
6
+ class Redis
7
+ attr_reader :config, :store
8
+
9
+ DEFAULTS = {
10
+ :host => 'localhost',
11
+ :port => 6379,
12
+ :namespace => :githu3,
13
+ :expire => 120
14
+ } unless defined?(DEFAULTS)
15
+
16
+ def initialize opts={}
17
+ @config = DEFAULTS.merge(opts || {})
18
+ redis = ::Redis.new :host => @config[:host], :port => @config[:port]
19
+ @store = ::Redis::Namespace.new(@config[:namespace].to_sym, :redis => redis)
20
+ end
21
+
22
+ def get k
23
+ val = @store[k.to_s]
24
+ val = Marshal.load val unless val.nil?
25
+ val
26
+ end
27
+
28
+ def set k, val, opts={}
29
+ @store[k.to_s] = Marshal.dump(val)
30
+ @store.expire k.to_s, (opts[:expire] || @config[:expire]).to_i
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,8 @@
1
+ module Githu3
2
+
3
+ module Cache
4
+ autoload :Redis, "githu3/cache/redis"
5
+ autoload :Disk, "githu3/cache/disk"
6
+ end
7
+
8
+ end
data/lib/githu3/cli.rb ADDED
@@ -0,0 +1,25 @@
1
+ require 'rubygems'
2
+ require 'githu3'
3
+ require 'thor'
4
+ require 'yaml'
5
+
6
+ module Githu3
7
+
8
+ class CLI < Thor
9
+
10
+ desc "issues", "get the latest issues from a repo"
11
+ def issues repo_name
12
+ client = Githu3::Client.new
13
+ begin
14
+ repo = client.repo(repo_name)
15
+ repo.issues.map do |issue|
16
+ puts [issue.number.to_s.ljust(5), issue.assignee.to_s.ljust(25), issue.title.to_s].join("\t|\t")
17
+ end
18
+ rescue => err
19
+ puts "Error: #{err.class.name}"
20
+ end
21
+ end
22
+
23
+ end
24
+
25
+ end
data/lib/githu3/client.rb CHANGED
@@ -1,48 +1,46 @@
1
1
  require 'faraday'
2
- require 'faraday_middleware'
3
2
  require 'faraday/response/raise_githu3_error'
3
+ require 'faraday/response/parse_json'
4
4
  require 'uri'
5
+ require 'forwardable'
5
6
  require 'active_support/core_ext/hash'
6
7
 
7
8
  module Githu3
8
9
 
9
10
  class Client
10
11
 
12
+ extend Forwardable
13
+
11
14
  BaseUrl = "https://api.github.com"
12
15
 
13
- attr_reader :conn, :rate_limit
16
+ def_delegator :conn, :rate_limit
17
+
18
+ attr_reader :conn, :auth
14
19
 
15
- def initialize(oauth_token=nil)
16
- headers = {}
17
- headers["Authorization"] = "token #{oauth_token}" if oauth_token
18
- @conn = Faraday.new({
19
- :url => Githu3::Client::BaseUrl,
20
- :headers => headers
21
- })
22
-
23
- @conn.use Faraday::Response::ParseJson
24
- @conn.use Faraday::Response::RaiseGithu3Error
25
-
26
- @rate_limit = {}
27
- @conn
20
+ def initialize(*args)
21
+ opts = args.extract_options!
22
+ @conn = Githu3::Connection.new opts do |c|
23
+ case args.length
24
+ when 1
25
+ @auth = :token
26
+ c.headers["Authorization"] = "token #{args.first}"
27
+ when 2
28
+ @auth = :basic
29
+ c.basic_auth(*args)
30
+ end
31
+ end
28
32
  end
29
-
33
+
34
+ def authenticated?
35
+ !!@auth
36
+ end
37
+
30
38
  def get *args
31
39
  opts = args.extract_options!
32
40
  uri = URI.parse(args.shift)
33
- uri_params = (opts[:params] || {}).stringify_keys
34
- unless uri.query.nil?
35
- uri_params.merge(uri.query.split("&").inject({}) { |m,p| k,v=p.split("=", 2); m.merge(k => v) } )
36
- end
37
- args.unshift uri.path
38
- res = @conn.get(*args) do |req|
39
- req.params = uri_params
40
- if opts[:params].is_a?(Hash)
41
- opts[:params].each { |k,v| req.params[k.to_s] = v.to_s }
42
- end
43
- end
44
- @rate_limit[:limit] = res.headers["x-ratelimit-limit"]
45
- @rate_limit[:remaining] = res.headers["x-ratelimit-remaining"]
41
+ uri.query = (opts[:params] || {}).stringify_keys.merge(Hash.from_url_params(uri.query || "")).to_url_params
42
+
43
+ res = @conn.get(uri, opts[:headers])
46
44
  res
47
45
  end
48
46
 
@@ -56,33 +54,51 @@ module Githu3
56
54
  # My stuf...
57
55
 
58
56
  def me
57
+ require_auth
59
58
  Githu3::User.new "/user", self
60
59
  end
61
60
 
62
61
  def orgs params={}
62
+ require_auth
63
63
  Githu3::ResourceCollection.new(self, Githu3::Org, "/user/orgs", params)
64
64
  end
65
65
 
66
66
  def repos params={}
67
+ require_auth
67
68
  Githu3::ResourceCollection.new(self, Githu3::Repo, "/user/repos", params)
68
69
  end
69
70
 
71
+ def teams
72
+ require_auth
73
+ Githu3::ResourceCollection.new(self, Githu3::Team, "/user/teams")
74
+ end
75
+
70
76
  def followers params={}
77
+ require_auth
71
78
  Githu3::ResourceCollection.new(self, Githu3::User, "/user/followers", params)
72
79
  end
73
80
 
74
81
  def following params={}
82
+ require_auth
75
83
  Githu3::ResourceCollection.new(self, Githu3::User, "/user/following", params)
76
84
  end
77
85
 
78
86
  def following?(other_user)
87
+ require_auth
79
88
  begin
80
89
  get("/user/following/#{other_user}").status == 204
81
90
  rescue Githu3::NotFound
82
91
  false
83
92
  end
84
93
  end
85
-
94
+
95
+ protected
96
+
97
+ def require_auth
98
+ raise Githu3::Unauthorized, "You must me logged in to use this method" unless authenticated?
99
+ yield if block_given?
100
+ end
101
+
86
102
  end
87
103
 
88
104
  end
@@ -1,5 +1,20 @@
1
1
  module Githu3
2
2
  class Comment < Githu3::Resource
3
3
 
4
+ embeds_one :user
5
+
6
+ def _type
7
+ m = url.match(/(issues|gists|pulls)\/comments\/[0-9]+$/)
8
+ if m.nil? || m[1].nil?
9
+ "commitcomment"
10
+ else
11
+ "#{m[1].singularize}comment"
12
+ end
13
+ end
14
+
15
+ def _mime_type mt
16
+ "application/vnd.github-#{_type}.#{mt}+json"
17
+ end
18
+
4
19
  end
5
20
  end
@@ -0,0 +1,13 @@
1
+ module Githu3
2
+ class Commit < Githu3::Resource
3
+
4
+ embeds_one :committer, :class_name => :user
5
+ embeds_one :author, :class_name => :user
6
+ embeds_one :commit, :class_name => :git_commit
7
+
8
+ def message
9
+ _attributes.message || commit.message rescue nil
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,47 @@
1
+ require 'digest/sha1'
2
+
3
+ module Githu3
4
+
5
+ class Connection
6
+
7
+ attr_reader :rate_limit, :cache, :conn
8
+
9
+
10
+
11
+ def initialize opts={}
12
+ @conn = Faraday.new({ :url => Githu3::Client::BaseUrl })
13
+
14
+ @conn.adapter opts[:adapter] if opts[:adapter]
15
+ @conn.use Faraday::Response::ParseJson
16
+ @conn.use Faraday::Response::RaiseGithu3Error
17
+
18
+ if opts[:cache]
19
+ cache_klass = Githu3::Cache.const_get(opts[:cache].to_s.camelize)
20
+ @cache = cache_klass.new(opts[:cache_config])
21
+ end
22
+
23
+ yield @conn if block_given?
24
+
25
+ @rate_limit = {}
26
+ end
27
+
28
+ def get url, headers={}, opts={}
29
+ use_cache = !@cache.nil? && !opts[:bypass_cache]
30
+ if use_cache
31
+ ref = Digest::SHA1.hexdigest [url, headers.to_s].join("")
32
+ res = @cache.get ref
33
+ return res unless res.nil?
34
+ end
35
+ res = @conn.get(url, headers)
36
+ if use_cache
37
+ @cache.set(ref, res) if res.status < 400
38
+ else
39
+ @rate_limit[:limit] = res.headers["x-ratelimit-limit"]
40
+ @rate_limit[:remaining] = res.headers["x-ratelimit-remaining"]
41
+ end
42
+ res
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,18 @@
1
+ class Hash
2
+ def to_url_params
3
+ elements = []
4
+ keys.size.times do |i|
5
+ elements << "#{keys[i]}=#{values[i]}"
6
+ end
7
+ elements.join('&')
8
+ end
9
+
10
+ def self.from_url_params(url_params="")
11
+ result = {}
12
+ url_params.split('&').each do |element|
13
+ element = element.split('=')
14
+ result[element[0]] = element[1]
15
+ end
16
+ result
17
+ end
18
+ end
@@ -0,0 +1,4 @@
1
+ module Githu3
2
+ class Download < Githu3::Resource
3
+ end
4
+ end
data/lib/githu3/event.rb CHANGED
@@ -1,5 +1,11 @@
1
1
  module Githu3
2
2
  class Event < Githu3::Resource
3
3
 
4
+ embeds_one :issue
5
+
6
+ def to_s
7
+ "#{date}: #{actor['login']} #{event} #{issue.title}"
8
+ end
9
+
4
10
  end
5
11
  end
@@ -0,0 +1,5 @@
1
+ module Githu3
2
+ class GitCommit < Githu3::Resource
3
+
4
+ end
5
+ end
data/lib/githu3/issue.rb CHANGED
@@ -3,7 +3,16 @@ module Githu3
3
3
 
4
4
  has_many :events
5
5
  has_many :comments
6
- has_many :labels
7
6
 
7
+ # members
8
+ embeds_many :labels
9
+ embeds_one :user
10
+ embeds_one :milestone
11
+ embeds_one :assignee, :class_name => :user
12
+
13
+ def _mime_type mt
14
+ "application/vnd.github-issue.#{mt}+json"
15
+ end
16
+
8
17
  end
9
18
  end
data/lib/githu3/org.rb CHANGED
@@ -5,7 +5,7 @@ module Githu3
5
5
 
6
6
  has_many :repos
7
7
  has_many :teams
8
- has_many :members, :class_name => :user
8
+ has_many :members, :class_name => :user
9
9
  has_many :public_members, :class_name => :user
10
10
 
11
11
  def member?(user_login)
@@ -0,0 +1,9 @@
1
+ module Githu3
2
+ class Pull < Githu3::Resource
3
+
4
+ def to_s
5
+ url || html_url
6
+ end
7
+
8
+ end
9
+ end
data/lib/githu3/ref.rb ADDED
@@ -0,0 +1,9 @@
1
+ module Githu3
2
+ class Ref < Githu3::Resource
3
+
4
+ def to_s
5
+ url || html_url
6
+ end
7
+
8
+ end
9
+ end
@@ -1,6 +1,26 @@
1
1
  module Githu3
2
2
 
3
3
  module Relations
4
+
5
+ def embeds_one m, opts={}
6
+ opts[:class_name] ||= m.to_s
7
+ define_method(m) do
8
+ klass = Githu3.const_get(opts[:class_name].to_s.camelize)
9
+ data = self._attributes.send(m)
10
+ klass.new(data, @client) unless data.nil?
11
+ end
12
+ end
13
+
14
+ def embeds_many m, opts={}
15
+ opts[:class_name] ||= m.to_s.singularize
16
+ define_method(m) do
17
+ klass = Githu3.const_get(opts[:class_name].to_s.camelize)
18
+ data = self._attributes.send(m)
19
+ data.map { |o| klass.new(o, @client) } unless data.nil?
20
+ end
21
+ end
22
+
23
+
4
24
  def has_many m, opts={}
5
25
  opts[:class_name] ||= m.to_s.singularize
6
26
  define_method(m) do |*args|
@@ -8,9 +28,9 @@ module Githu3
8
28
  klass = Githu3.const_get(opts[:class_name].to_s.camelize)
9
29
  _resource_path = [opts[:nested_in], m].compact.join("/")
10
30
  if args.length == 1
11
- klass.new([path, _resource_path, args.first].join("/"), @client)
31
+ klass.new([_path, _resource_path, args.first].join("/"), @client)
12
32
  else
13
- Githu3::ResourceCollection.new(@client, klass, [path, _resource_path].join("/"), params)
33
+ Githu3::ResourceCollection.new(@client, klass, [_path, _resource_path].join("/"), params)
14
34
  end
15
35
  end
16
36
  end