gh 0.0.1 → 0.1.0

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