aptible-resource 0.3.5 → 0.3.6
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.
- checksums.yaml +4 -4
- data/.travis.yml +3 -1
- data/lib/aptible/resource/base.rb +35 -12
- data/lib/aptible/resource/version.rb +1 -1
- data/spec/aptible/resource/base_spec.rb +118 -32
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31f491541f4e8330accd97a53c1896fe7fca26e2
|
4
|
+
data.tar.gz: fa2f72d22a0736be3d38d61d4731e7582ef64c78
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ea9ed96d16623b924cc4bbd463e128bab5d8ce1463a10451faa3de64be1b079c88aec56efad7ad079b7fea3877cd906c9bae5b24b2048d08ad99bdfa5f23a4a0
|
7
|
+
data.tar.gz: 406299c0d2a4cff3faca28f86c736374a27f38cde09ea6d050a127f74853e6d5916477d4bf03cc5feb228a4ee9cc7c8151151dbace303c8f44fab0a847c8333b
|
data/.travis.yml
CHANGED
@@ -38,18 +38,29 @@ module Aptible
|
|
38
38
|
name.split('::').last.underscore.pluralize
|
39
39
|
end
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
resource
|
41
|
+
def self.each_page(options = {})
|
42
|
+
return unless block_given?
|
43
|
+
href = options[:href] || collection_href
|
44
|
+
while href
|
45
|
+
# TODO: Breaking here is consistent with the existing behavior of
|
46
|
+
# .all, but it essentially swallows an error if the page you're
|
47
|
+
# hitting happens to 404. This should probably be addressed in an
|
48
|
+
# effort to make this API client more strict.
|
49
|
+
resource = find_by_url(href, options)
|
50
|
+
break if resource.nil?
|
51
|
+
|
52
|
+
yield resource.entries
|
53
|
+
|
54
|
+
next_link = resource.links['next']
|
55
|
+
href = next_link ? next_link.href : nil
|
50
56
|
end
|
51
57
|
end
|
52
|
-
|
58
|
+
|
59
|
+
def self.all(options = {})
|
60
|
+
out = []
|
61
|
+
each_page(options) { |page| out.concat page }
|
62
|
+
out
|
63
|
+
end
|
53
64
|
|
54
65
|
def self.where(options = {})
|
55
66
|
params = options.except(:token, :root, :namespace, :headers)
|
@@ -89,7 +100,7 @@ module Aptible
|
|
89
100
|
|
90
101
|
# rubocop:disable PredicateName
|
91
102
|
def self.has_many(relation)
|
92
|
-
|
103
|
+
define_has_many_getters(relation)
|
93
104
|
define_has_many_setter(relation)
|
94
105
|
end
|
95
106
|
# rubocop:enable PredicateName
|
@@ -126,7 +137,9 @@ module Aptible
|
|
126
137
|
end
|
127
138
|
# rubocop:enable PredicateName
|
128
139
|
|
129
|
-
|
140
|
+
# rubocop:disable MethodLength
|
141
|
+
# rubocop:disable AbcSize
|
142
|
+
def self.define_has_many_getters(relation)
|
130
143
|
define_method relation do
|
131
144
|
get unless loaded
|
132
145
|
if (memoized = instance_variable_get("@#{relation}"))
|
@@ -137,7 +150,17 @@ module Aptible
|
|
137
150
|
instance_variable_set("@#{relation}", depaginated)
|
138
151
|
end
|
139
152
|
end
|
153
|
+
|
154
|
+
define_method "each_#{relation.to_s.singularize}" do |&block|
|
155
|
+
return if block.nil?
|
156
|
+
self.class.each_page(href: links[relation].base_href,
|
157
|
+
headers: headers) do |page|
|
158
|
+
page.each { |entry| block.call entry }
|
159
|
+
end
|
160
|
+
end
|
140
161
|
end
|
162
|
+
# rubocop:enable AbcSize
|
163
|
+
# rubocop:enable MethodLength
|
141
164
|
|
142
165
|
def self.embeds_one(relation)
|
143
166
|
define_method relation do
|
@@ -9,6 +9,39 @@ describe Aptible::Resource::Base do
|
|
9
9
|
error_response.stub(:status) { 403 }
|
10
10
|
end
|
11
11
|
|
12
|
+
shared_context 'paginated collection' do
|
13
|
+
let(:urls) { ['/mainframes', '/mainframes?page=1'] }
|
14
|
+
let(:calls) { [] }
|
15
|
+
|
16
|
+
before do
|
17
|
+
pages = {}
|
18
|
+
|
19
|
+
urls.each_with_index do |url, idx|
|
20
|
+
collection = double("Collection for #{url}")
|
21
|
+
links = {}
|
22
|
+
|
23
|
+
allow(collection).to receive(:entries).and_return(["At #{url}"])
|
24
|
+
allow(collection).to receive(:links).and_return(links)
|
25
|
+
|
26
|
+
next_url = urls[idx + 1]
|
27
|
+
if next_url
|
28
|
+
links['next'] = HyperResource::Link.new(nil, 'href' => next_url)
|
29
|
+
end
|
30
|
+
|
31
|
+
pages[url] = collection
|
32
|
+
end
|
33
|
+
|
34
|
+
[Api, Api::Mainframe].each do |klass|
|
35
|
+
allow_any_instance_of(klass).to receive(:find_by_url) do |u, _|
|
36
|
+
calls << u
|
37
|
+
page = pages[u]
|
38
|
+
fail "Accessed unexpected URL #{u}" if page.nil?
|
39
|
+
page
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
12
45
|
subject { Api.new }
|
13
46
|
|
14
47
|
describe '.collection_href' do
|
@@ -33,47 +66,72 @@ describe Aptible::Resource::Base do
|
|
33
66
|
end
|
34
67
|
|
35
68
|
describe '.all' do
|
36
|
-
|
37
|
-
|
69
|
+
context 'when not paginated' do
|
70
|
+
let(:mainframe) { double 'Mainframe' }
|
71
|
+
let(:collection) { double 'Api' }
|
38
72
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
73
|
+
before do
|
74
|
+
collection.stub(:entries) { [mainframe] }
|
75
|
+
collection.stub(:links) { Hash.new }
|
76
|
+
Api::Mainframe.any_instance.stub(:find_by_url) { collection }
|
77
|
+
end
|
44
78
|
|
45
|
-
|
46
|
-
|
47
|
-
|
79
|
+
it 'should be an array' do
|
80
|
+
expect(Api::Mainframe.all).to be_a Array
|
81
|
+
end
|
48
82
|
|
49
|
-
|
50
|
-
|
51
|
-
|
83
|
+
it 'should return the root collection' do
|
84
|
+
expect(Api::Mainframe.all).to eq [mainframe]
|
85
|
+
end
|
52
86
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
87
|
+
it 'should pass options to the HyperResource initializer' do
|
88
|
+
klass = Api::Mainframe
|
89
|
+
options = { token: 'token' }
|
90
|
+
expect(klass).to receive(:new).with(options).and_return klass.new
|
91
|
+
Api::Mainframe.all(options)
|
92
|
+
end
|
58
93
|
end
|
59
94
|
|
60
95
|
context 'when paginated' do
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
)
|
66
|
-
|
67
|
-
|
68
|
-
)
|
96
|
+
include_context 'paginated collection'
|
97
|
+
|
98
|
+
it 'should collect entries from all pages' do
|
99
|
+
records = Api::Mainframe.all
|
100
|
+
expect(records.size).to eq(2)
|
101
|
+
expect(records.first).to eq('At /mainframes')
|
102
|
+
expect(records.second).to eq('At /mainframes?page=1')
|
103
|
+
expect(calls).to eq(urls)
|
69
104
|
end
|
70
105
|
|
71
|
-
it
|
72
|
-
|
106
|
+
it "should return an empty list for a URL that doesn't exist" do
|
107
|
+
allow_any_instance_of(Api::Mainframe).to receive(:find_by_url) { nil }
|
108
|
+
expect(Api::Mainframe.all).to eq([])
|
73
109
|
end
|
74
110
|
end
|
75
111
|
end
|
76
112
|
|
113
|
+
describe '.each_page' do
|
114
|
+
include_context 'paginated collection'
|
115
|
+
|
116
|
+
it 'should iterate over all pages' do
|
117
|
+
pages = 0
|
118
|
+
Api::Mainframe.each_page { pages += 1 }
|
119
|
+
expect(pages).to eq(2)
|
120
|
+
expect(calls).to eq(urls)
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'should find all records' do
|
124
|
+
records = ['At /mainframes', 'At /mainframes?page=1']
|
125
|
+
Api::Mainframe.each_page { |p| expect(p).to eq([records.shift]) }
|
126
|
+
expect(calls).to eq(urls)
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should not access more URLs if the consumer breaks' do
|
130
|
+
Api::Mainframe.each_page { break }
|
131
|
+
expect(calls).to eq(['/mainframes'])
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
77
135
|
describe '.create' do
|
78
136
|
let(:mainframe) { Api::Mainframe.new }
|
79
137
|
let(:mainframes_link) { HyperResource::Link.new(href: '/mainframes') }
|
@@ -263,10 +321,38 @@ describe Aptible::Resource::Base do
|
|
263
321
|
end
|
264
322
|
|
265
323
|
describe '#{relation}s' do
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
subject.mainframes
|
324
|
+
include_context 'paginated collection'
|
325
|
+
|
326
|
+
it 'should return all records' do
|
327
|
+
records = subject.mainframes
|
328
|
+
|
329
|
+
expect(records.size).to eq(2)
|
330
|
+
expect(records.first).to eq('At /mainframes')
|
331
|
+
expect(records.second).to eq('At /mainframes?page=1')
|
332
|
+
expect(calls).to eq(urls)
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
describe 'each_#{relation}' do
|
337
|
+
include_context 'paginated collection'
|
338
|
+
|
339
|
+
it 'should iterate over all records' do
|
340
|
+
records = []
|
341
|
+
subject.each_mainframe { |mainframe| records << mainframe }
|
342
|
+
|
343
|
+
expect(records.size).to eq(2)
|
344
|
+
expect(records.first).to eq('At /mainframes')
|
345
|
+
expect(records.second).to eq('At /mainframes?page=1')
|
346
|
+
expect(calls).to eq(urls)
|
347
|
+
end
|
348
|
+
|
349
|
+
it 'should stop iterating when the consumer breaks' do
|
350
|
+
subject.each_mainframe { |_| break }
|
351
|
+
expect(calls).to eq([urls[0]])
|
352
|
+
end
|
353
|
+
|
354
|
+
it 'should not fail if not passed a block' do
|
355
|
+
subject.each_mainframe
|
270
356
|
end
|
271
357
|
end
|
272
358
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aptible-resource
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Frank Macreery
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-06-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: uri_template
|
@@ -225,7 +225,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
225
225
|
version: '0'
|
226
226
|
requirements: []
|
227
227
|
rubyforge_project:
|
228
|
-
rubygems_version: 2.
|
228
|
+
rubygems_version: 2.6.4
|
229
229
|
signing_key:
|
230
230
|
specification_version: 4
|
231
231
|
summary: Foundation classes for Aptible resource server gems
|