gh 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -10,3 +10,8 @@ rvm:
10
10
  - ruby-head
11
11
  - jruby-head
12
12
  - ree
13
+ matrix:
14
+ allow_failures:
15
+ - rvm: ruby-head
16
+ - rvm: rbx-18mode
17
+ - rvm: rbx-19mode
data/README.md CHANGED
@@ -22,4 +22,17 @@ api = GH::Stack.build do
22
22
  use GH::Normalizer
23
23
  use GH::Remote, username: "admin", password: "admin"
24
24
  end
25
- ```
25
+ ```
26
+
27
+ Usage example:
28
+
29
+ ``` ruby
30
+ GH.with username: 'rkh' password: 'abc123' do
31
+ sven = GH['users/svenfuchs']
32
+
33
+ if sven['hireable']
34
+ # recruiter has to be provided by some different library
35
+ Recruiter.contact sven['email']
36
+ end
37
+ end
38
+ ```
data/lib/gh.rb CHANGED
@@ -5,26 +5,34 @@ require 'forwardable'
5
5
  module GH
6
6
  autoload :Cache, 'gh/cache'
7
7
  autoload :Case, 'gh/case'
8
+ autoload :LazyLoader, 'gh/lazy_loader'
8
9
  autoload :Normalizer, 'gh/normalizer'
9
10
  autoload :Remote, 'gh/remote'
10
11
  autoload :Response, 'gh/response'
11
12
  autoload :Stack, 'gh/stack'
12
13
  autoload :Wrapper, 'gh/wrapper'
13
14
 
14
- def self.[](key)
15
- backend = Thread.current[:GH] ||= DefaultStack.build
16
- backend[key]
17
- end
18
-
19
15
  def self.with(backend)
20
16
  backend = DefaultStack.build(backend) if Hash === backend
21
- was, Thread.current[:GH] = Thread.current[:GH], backend
17
+ was, self.current = current, backend
22
18
  yield
23
19
  ensure
24
- Thread.current[:GH] = was
20
+ self.current = was
21
+ end
22
+
23
+ def self.current
24
+ Thread.current[:GH] ||= DefaultStack.new
25
25
  end
26
26
 
27
+ def self.current=(backend)
28
+ Thread.current[:GH] = backend
29
+ end
30
+
31
+ extend SingleForwardable
32
+ def_delegators :current, :api_host, :[], :reset
33
+
27
34
  DefaultStack = Stack.new do
35
+ use LazyLoader
28
36
  use Cache
29
37
  use Normalizer
30
38
  use Remote
@@ -2,8 +2,7 @@ require 'gh'
2
2
  require 'thread'
3
3
 
4
4
  module GH
5
- # Public: This class deals with HTTP requests to Github. It is the base Wrapper you always want to use.
6
- # Note that it is usually used implicitely by other wrapper classes if not specified.
5
+ # Public: This class caches responses.
7
6
  class Cache < Wrapper
8
7
  # Public: Get/set cache to use. Compatible with Rails/ActiveSupport cache.
9
8
  attr_accessor :cache
@@ -20,9 +19,14 @@ module GH
20
19
  # Internal: Tries to fetch a value from the cache and if it doesn't exist, generates it from the
21
20
  # block given.
22
21
  def fetch(key)
23
- @mutex.lock { @old, @new = @new, {} if @new.size > @size } if @new.size > @size
22
+ @mutex.synchronize { @old, @new = @new, {} if @new.size > @size } if @new.size > @size
24
23
  @new[key] ||= @old[key] || yield
25
24
  end
25
+
26
+ # Internal: ...
27
+ def clear
28
+ @mutex.synchronize { @old, @new = {}, {} }
29
+ end
26
30
  end
27
31
 
28
32
  # Internal: Initializes a new Cache instance.
@@ -33,6 +37,12 @@ module GH
33
37
  super
34
38
  end
35
39
 
40
+ # Public: ...
41
+ def reset
42
+ super
43
+ clear_partial or clear_all
44
+ end
45
+
36
46
  # Public: Retrieves resources from Github and caches response for future access.
37
47
  #
38
48
  # Examples
@@ -41,7 +51,22 @@ module GH
41
51
  #
42
52
  # Returns the Response.
43
53
  def [](key)
44
- cache.fetch(path_for(key)) { super }
54
+ cache.fetch(prefixed(key)) { super }
55
+ end
56
+
57
+ private
58
+
59
+ def clear_partial
60
+ return false unless cache.respond_to? :delete_matched
61
+ pattern = "^" << Regexp.escape(prefixed(""))
62
+ cache.delete_matched Regexp.new(pattern)
63
+ true
64
+ rescue NotImplementedError
65
+ false
66
+ end
67
+
68
+ def clear_all
69
+ cache.clear
45
70
  end
46
71
  end
47
72
  end
@@ -0,0 +1,21 @@
1
+ require 'gh'
2
+
3
+ module GH
4
+ # Public: ...
5
+ class LazyLoader < Wrapper
6
+ double_dispatch
7
+
8
+ def modify_hash(hash)
9
+ hash = super
10
+ link = hash['_links'].try(:[], 'self')
11
+ setup_lazy_loading(hash, link['href']) if link
12
+ hash
13
+ end
14
+
15
+ private
16
+
17
+ def lazy_load(hash, key, link)
18
+ backend[link]
19
+ end
20
+ end
21
+ end
@@ -9,15 +9,13 @@ module GH
9
9
  # Returns normalized Response.
10
10
  def [](key)
11
11
  result = super
12
- links(result)['self'] ||= { 'href' => full_url(key).to_s } if result.hash?
12
+ links(result)['self'] ||= { 'href' => full_url(key).to_s } if result.respond_to? :to_hash
13
13
  result
14
14
  end
15
15
 
16
16
  private
17
17
 
18
- def modify(*)
19
- normalize super
20
- end
18
+ double_dispatch
21
19
 
22
20
  def links(hash)
23
21
  hash = hash.data if hash.respond_to? :data
@@ -28,32 +26,32 @@ module GH
28
26
  links(hash)[type] = {"href" => href}
29
27
  end
30
28
 
31
- def normalize_response(response)
29
+ def modify_response(response)
32
30
  response = response.dup
33
- response.data = normalize response.data
31
+ response.data = modify response.data
34
32
  response
35
33
  end
36
34
 
37
- def normalize_hash(hash)
35
+ def modify_hash(hash)
38
36
  corrected = {}
39
37
  corrected.default_proc = hash.default_proc if hash.default_proc
40
38
 
41
39
  hash.each_pair do |key, value|
42
- key = normalize_key(key, value)
43
- next if normalize_url(corrected, key, value)
44
- next if normalize_time(corrected, key, value)
45
- corrected[key] = normalize(value)
40
+ key = modify_key(key, value)
41
+ next if modify_url(corrected, key, value)
42
+ next if modify_time(corrected, key, value)
43
+ corrected[key] = modify(value)
46
44
  end
47
45
 
48
- normalize_user(corrected)
46
+ modify_user(corrected)
49
47
  corrected
50
48
  end
51
49
 
52
- def normalize_time(hash, key, value)
50
+ def modify_time(hash, key, value)
53
51
  hash['date'] = Time.at(value).xmlschema if key == 'timestamp'
54
52
  end
55
53
 
56
- def normalize_user(hash)
54
+ def modify_user(hash)
57
55
  hash['owner'] ||= hash.delete('user') if hash['created_at'] and hash['user']
58
56
  hash['author'] ||= hash.delete('user') if hash['committed_at'] and hash['user']
59
57
 
@@ -61,7 +59,7 @@ module GH
61
59
  hash['author'] ||= hash['committer'] if hash['committer']
62
60
  end
63
61
 
64
- def normalize_url(hash, key, value)
62
+ def modify_url(hash, key, value)
65
63
  case key
66
64
  when "blog"
67
65
  set_link(hash, key, value)
@@ -73,14 +71,14 @@ module GH
73
71
  end
74
72
  end
75
73
 
76
- def normalize_key(key, value = nil)
74
+ def modify_key(key, value = nil)
77
75
  case key
78
76
  when 'gravatar_url' then 'avatar_url'
79
77
  when 'org' then 'organization'
80
78
  when 'orgs' then 'organizations'
81
79
  when 'username' then 'login'
82
80
  when 'repo' then 'repository'
83
- when 'repos' then normalize_key('repositories', value)
81
+ when 'repos' then modify_key('repositories', value)
84
82
  when /^repos?_(.*)$/ then "repository_#{$1}"
85
83
  when /^(.*)_repo$/ then "#{$1}_repository"
86
84
  when /^(.*)_repos$/ then "#{$1}_repositories"
@@ -92,18 +90,5 @@ module GH
92
90
  else key
93
91
  end
94
92
  end
95
-
96
- def normalize_array(array)
97
- array.map { |e| normalize(e) }
98
- end
99
-
100
- def normalize(object)
101
- case object
102
- when Hash then normalize_hash(object)
103
- when Array then normalize_array(object)
104
- when Response then normalize_response(object)
105
- else object
106
- end
107
- end
108
93
  end
109
94
  end
@@ -5,7 +5,7 @@ module GH
5
5
  # Public: This class deals with HTTP requests to Github. It is the base Wrapper you always want to use.
6
6
  # Note that it is usually used implicitely by other wrapper classes if not specified.
7
7
  class Remote < Wrapper
8
- attr_reader :api_host, :connection, :headers
8
+ attr_reader :api_host, :connection, :headers, :prefix
9
9
 
10
10
  # Public: Generates a new Rempte instance.
11
11
  #
@@ -33,6 +33,11 @@ module GH
33
33
  "Accept-Charset" => "utf-8"
34
34
  }
35
35
 
36
+ @prefix = ""
37
+ @prefix << "#{token}@" if token
38
+ @prefix << "#{username}:#{password}@" if username and password
39
+ @prefix << @api_host.host
40
+
36
41
  @connection = Faraday.new(:url => api_host) do |builder|
37
42
  builder.request(:token_auth, token) if token
38
43
  builder.request(:basic_auth, username, password) if username and password
@@ -61,8 +66,21 @@ module GH
61
66
  modify(response.body, response.headers)
62
67
  end
63
68
 
69
+ # Public: ...
70
+ def reset
71
+ end
72
+
73
+ # Public: ...
74
+ def load(data)
75
+ modify(data)
76
+ end
77
+
64
78
  private
65
79
 
80
+ def identifier(key)
81
+ path_for(key)
82
+ end
83
+
66
84
  def modify(body, headers = {})
67
85
  return body if body.is_a? Response
68
86
  Response.new(headers, body)
@@ -69,8 +69,9 @@ module GH
69
69
  @data.dup.to_ary
70
70
  end
71
71
 
72
- def hash?
73
- respond_to? :to_hash
72
+ # Public: ...
73
+ def to_gh
74
+ self
74
75
  end
75
76
 
76
77
  protected
@@ -48,5 +48,12 @@ module GH
48
48
  klass.new backend, @options.merge(opts).merge(options)
49
49
  end
50
50
  end
51
+
52
+ # Public: ...
53
+ def replace(old_class, new_class)
54
+ @stack.map! { |klass, options| [old_class == klass ? new_class : klass, options] }
55
+ end
56
+
57
+ alias_method :new, :build
51
58
  end
52
59
  end
@@ -1,4 +1,4 @@
1
1
  module GH
2
2
  # Public: Library version.
3
- VERSION = "0.0.1"
3
+ VERSION = "0.1.0"
4
4
  end
@@ -22,6 +22,7 @@ module GH
22
22
  # end
23
23
  class Wrapper
24
24
  extend Forwardable
25
+ include Case
25
26
 
26
27
  # Public: Get wrapped layer.
27
28
  attr_reader :backend
@@ -29,6 +30,11 @@ module GH
29
30
  # Public: Returns the URI used for sending out web request.
30
31
  def_delegator :backend, :api_host
31
32
 
33
+ # Public: Retrieves resources from Github.
34
+ def self.[](key)
35
+ new[key]
36
+ end
37
+
32
38
  # Public: Retrieves resources from Github.
33
39
  #
34
40
  # By default, this method is delegated to the next layer on the stack
@@ -40,7 +46,7 @@ module GH
40
46
  # Internal: Get/set default layer to wrap when creating a new instance.
41
47
  def self.wraps(klass = nil)
42
48
  @wraps = klass if klass
43
- @wraps || Remote
49
+ @wraps ||= Remote
44
50
  end
45
51
 
46
52
  # Public: Initialize a new Wrapper.
@@ -54,6 +60,7 @@ module GH
54
60
 
55
61
  # Public: Set wrapped layer.
56
62
  def backend=(layer)
63
+ reset
57
64
  layer.frontend = self
58
65
  @backend = layer
59
66
  end
@@ -68,16 +75,75 @@ module GH
68
75
  @frontend ? @frontend.frontend : self
69
76
  end
70
77
 
78
+ # Public: ...
71
79
  def inspect
72
80
  "#<#{self.class}: #{backend.inspect}>"
73
81
  end
74
82
 
83
+ # Internal: ...
84
+ def prefixed(key)
85
+ prefix + "#" + identifier(key)
86
+ end
87
+
88
+ # Public: ...
89
+ def reset
90
+ backend.reset if backend
91
+ end
92
+
93
+ # Public: ...
94
+ def load(data)
95
+ modify backend.load(data)
96
+ end
97
+
75
98
  private
76
99
 
77
- def modify(data)
100
+ def identifier(key)
101
+ backend.prefixed(key)
102
+ end
103
+
104
+ def prefix
105
+ self.class.name
106
+ end
107
+
108
+ def self.double_dispatch
109
+ define_method(:modify) { |data| double_dispatch(data) }
110
+ end
111
+
112
+ def double_dispatch(data)
113
+ case data
114
+ when respond_to(:to_gh) then modify_response(data)
115
+ when respond_to(:to_hash) then modify_hash(data)
116
+ when respond_to(:to_ary) then modify_array(data)
117
+ when respond_to(:to_str) then modify_string(data)
118
+ when respond_to(:to_int) then modify_integer(data)
119
+ else modify_unkown data
120
+ end
121
+ end
122
+
123
+ def modify_response(response)
124
+ result = double_dispatch response.data
125
+ result.respond_to?(:to_gh) ? result.to_gh : Response.new({}, result)
126
+ end
127
+
128
+ def modify(data, *)
78
129
  data
79
130
  end
80
131
 
132
+ def modify_array(array)
133
+ array.map { |e| modify(e) }
134
+ end
135
+
136
+ def modify_hash(hash, &block)
137
+ corrected = {}
138
+ hash.each_pair { |k,v| corrected[k] = modify(v) }
139
+ corrected.default_proc = hash.default_proc if hash.default_proc
140
+ corrected
141
+ end
142
+
143
+ alias modify_string modify
144
+ alias modify_integer modify
145
+ alias modify_unkown modify
146
+
81
147
  def setup(backend, options)
82
148
  self.backend = Wrapper === backend ? backend : self.class.wraps.new(backend, options)
83
149
  end
@@ -90,13 +156,33 @@ module GH
90
156
  end
91
157
 
92
158
  def full_url(key)
93
- api_host + path_for(key)
159
+ uri = api_host + Addressable::URI.parse(key)
160
+ raise ArgumentError, "URI out of scope: #{key}" if uri.host != api_host.host
161
+ uri
162
+ end
163
+
164
+ def setup_default_proc(hash, &block)
165
+ old_proc = hash.default_proc
166
+ hash.default_proc = proc do |hash, key|
167
+ value = old_proc.call(hash, key) if old_proc
168
+ value = block[hash, key] if value.nil?
169
+ value
170
+ end
171
+ end
172
+
173
+ def setup_lazy_loading(hash, *args)
174
+ loaded = false
175
+ setup_default_proc hash do |hash, key|
176
+ next if loaded
177
+ fields = lazy_load(hash, key, *args)
178
+ hash.merge! fields
179
+ loaded = true
180
+ fields[key]
181
+ end
94
182
  end
95
183
 
96
184
  def path_for(key)
97
- uri = Addressable::URI.parse(key)
98
- raise ArgumentError, "URI out of scope: #{key}" if uri.host and uri.host != api_host.host
99
- uri.request_uri
185
+ full_url(key).request_uri
100
186
  end
101
187
  end
102
188
  end
@@ -14,4 +14,15 @@ describe GH::Cache do
14
14
  subject['users/rkh']['name'].should be == "Konstantin Haase"
15
15
  requests.count.should be == 2
16
16
  end
17
+
18
+ it 'cache is resettable' do
19
+ subject['users/rkh']['name'].should be == "Konstantin Haase"
20
+ subject['users/rkh']['name'].should be == "Konstantin Haase"
21
+ requests.count.should be == 1
22
+
23
+ subject.reset
24
+ requests.count.should be == 0
25
+ subject['users/rkh']['name'].should be == "Konstantin Haase"
26
+ requests.count.should be == 1
27
+ end
17
28
  end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe GH do
4
+ it 'allows doing requests right from the GH object' do
5
+ GH['users/rkh']['name'].should be == "Konstantin Haase"
6
+ end
7
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe GH::LazyLoader do
4
+ before { subject.backend = GH::Normalizer.new(GH::MockBackend.new) }
5
+
6
+ let! :raw do
7
+ hash = subject.backend['users/rkh'].to_hash
8
+ hash.delete 'name'
9
+ hash
10
+ end
11
+
12
+ let :rkh do
13
+ subject.load(raw)
14
+ end
15
+
16
+ it 'send http requests for missing fields' do
17
+ should_request(1) { rkh['name'].should be == 'Konstantin Haase' }
18
+ end
19
+
20
+ it 'does not send http requests for existing fields' do
21
+ should_not_request { rkh['login'].should be == 'rkh' }
22
+ end
23
+
24
+ it 'allows traversing into nested structures' do
25
+ sven = subject.backend['users/svenfuchs'].to_hash
26
+ sven['friends'] = [raw]
27
+ sven.delete 'name'
28
+
29
+ sven = subject.load(sven)
30
+ should_request(1) { sven['friends'][0]['name'].should be == 'Konstantin Haase' }
31
+ end
32
+
33
+ it 'does not request twice if the field does not exist upstream' do
34
+ should_request(1) { 2.times { rkh['foo'] } }
35
+ end
36
+
37
+ it 'does not skip an already existing default proc' do
38
+ count = 0
39
+ raw.default_proc = proc { |hash, key| count += 1 if key == 'foo' }
40
+ rkh = subject.load(raw)
41
+
42
+ should_not_request do
43
+ rkh['foo'].should be == 1
44
+ rkh['foo'].should be == 2
45
+ end
46
+ end
47
+
48
+ it 'is still loading missing fields, even if a default proc is set' do
49
+ count = 0
50
+ raw.default_proc = proc { |hash, key| count += 1 if key == 'foo' }
51
+ rkh = subject.load(raw)
52
+
53
+ should_request 1 do
54
+ rkh['foo'].should be == 1
55
+ rkh['name'].should be == 'Konstantin Haase'
56
+ rkh['foo'].should be == 2
57
+ end
58
+ end
59
+ end
@@ -4,16 +4,16 @@ describe GH::Normalizer do
4
4
  before { subject.backend = GH::MockBackend.new }
5
5
 
6
6
  def normalize(payload)
7
- data['payload'] = payload
7
+ data['/payload'] = payload
8
8
  end
9
9
 
10
10
  def with_headers(headers = {})
11
11
  response = GH::Response.new(headers)
12
- data['payload'], response.data = response, data['payload']
12
+ data['/payload'], response.data = response, data['/payload']
13
13
  end
14
14
 
15
15
  def normalized
16
- subject['payload']
16
+ subject['/payload']
17
17
  end
18
18
 
19
19
  it 'is set up properly' do
@@ -25,6 +25,12 @@ describe GH::Normalizer do
25
25
  normalized['foo'].should be == 'bar'
26
26
  end
27
27
 
28
+ it 'allows normalization with #load' do
29
+ result = subject.load("org" => "foo")
30
+ result.should_not include("org")
31
+ result["organization"].should be == "foo"
32
+ end
33
+
28
34
  it 'works for deeply nested fields'
29
35
  it 'works for lists'
30
36
 
@@ -256,5 +262,10 @@ describe GH::Normalizer do
256
262
  normalized['_links'].should_not include('html')
257
263
  normalized['_links']['self']['href'].should be == 'http://api.github.com/foo'
258
264
  end
265
+
266
+ it 'passes through true' do
267
+ normalize 'foo' => true
268
+ normalized['foo'].should be == true
269
+ end
259
270
  end
260
271
  end
@@ -5,8 +5,9 @@ require 'fileutils'
5
5
 
6
6
  module GH
7
7
  module TestHelpers
8
- def backend
9
- subject.backend
8
+ def backend(layer = subject)
9
+ return layer if layer.backend.nil? or layer.is_a? MockBackend
10
+ backend layer.backend
10
11
  end
11
12
 
12
13
  def requests
@@ -16,6 +17,16 @@ module GH
16
17
  def data
17
18
  backend.data
18
19
  end
20
+
21
+ def should_request(num = 1, &block)
22
+ was = requests.count
23
+ yield
24
+ (requests.count - was).should be == num
25
+ end
26
+
27
+ def should_not_request(&block)
28
+ should_request(0, &block)
29
+ end
19
30
  end
20
31
 
21
32
  class MockBackend < Wrapper
@@ -45,6 +56,12 @@ module GH
45
56
  result
46
57
  end
47
58
 
59
+ def reset
60
+ super
61
+ @data.clear
62
+ @requests.clear
63
+ end
64
+
48
65
  private
49
66
 
50
67
  def allow_http
@@ -59,4 +76,6 @@ end
59
76
 
60
77
  RSpec.configure do |c|
61
78
  c.include GH::TestHelpers
79
+ c.before { GH::DefaultStack.replace GH::Remote, GH::MockBackend }
80
+ c.after { GH.reset }
62
81
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gh
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
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: 2012-03-22 00:00:00.000000000 Z
12
+ date: 2012-04-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70328844248000 !ruby/object:Gem::Requirement
16
+ requirement: &70185635369900 !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: *70328844248000
24
+ version_requirements: *70185635369900
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: webmock
27
- requirement: &70328844247440 !ruby/object:Gem::Requirement
27
+ requirement: &70185635369280 !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: *70328844247440
35
+ version_requirements: *70185635369280
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: faraday
38
- requirement: &70328844262860 !ruby/object:Gem::Requirement
38
+ requirement: &70185635368560 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0.7'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70328844262860
46
+ version_requirements: *70185635368560
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: backports
49
- requirement: &70328844262340 !ruby/object:Gem::Requirement
49
+ requirement: &70185635367800 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '2.3'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70328844262340
57
+ version_requirements: *70185635367800
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: multi_json
60
- requirement: &70328844261880 !ruby/object:Gem::Requirement
60
+ requirement: &70185635367120 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: '1.0'
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *70328844261880
68
+ version_requirements: *70185635367120
69
69
  description: multi-layer client for the github api v3
70
70
  email:
71
71
  - konstantin.mailinglists@googlemail.com
@@ -83,6 +83,7 @@ files:
83
83
  - lib/gh/cache.rb
84
84
  - lib/gh/case.rb
85
85
  - lib/gh/faraday.rb
86
+ - lib/gh/lazy_loader.rb
86
87
  - lib/gh/normalizer.rb
87
88
  - lib/gh/remote.rb
88
89
  - lib/gh/response.rb
@@ -90,6 +91,8 @@ files:
90
91
  - lib/gh/version.rb
91
92
  - lib/gh/wrapper.rb
92
93
  - spec/cache_spec.rb
94
+ - spec/gh_spec.rb
95
+ - spec/lazy_loader_spec.rb
93
96
  - spec/normalizer_spec.rb
94
97
  - spec/payloads/users/rkh.yml
95
98
  - spec/payloads/users/svenfuchs.yml
@@ -124,6 +127,8 @@ specification_version: 3
124
127
  summary: layered github client
125
128
  test_files:
126
129
  - spec/cache_spec.rb
130
+ - spec/gh_spec.rb
131
+ - spec/lazy_loader_spec.rb
127
132
  - spec/normalizer_spec.rb
128
133
  - spec/payloads/users/rkh.yml
129
134
  - spec/payloads/users/svenfuchs.yml