aptible-resource 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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.rubocop.yml +22 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.md +22 -0
- data/README.md +52 -0
- data/Rakefile +4 -0
- data/aptible-resource.gemspec +35 -0
- data/lib/aptible/resource.rb +7 -0
- data/lib/aptible/resource/adapter.rb +19 -0
- data/lib/aptible/resource/base.rb +70 -0
- data/lib/aptible/resource/model.rb +115 -0
- data/lib/aptible/resource/token.rb +10 -0
- data/lib/aptible/resource/version.rb +5 -0
- data/lib/hyper_resource.rb +302 -0
- data/lib/hyper_resource/adapter.rb +31 -0
- data/lib/hyper_resource/adapter/hal_json.rb +135 -0
- data/lib/hyper_resource/attributes.rb +100 -0
- data/lib/hyper_resource/exceptions.rb +40 -0
- data/lib/hyper_resource/link.rb +59 -0
- data/lib/hyper_resource/links.rb +63 -0
- data/lib/hyper_resource/modules/http.rb +131 -0
- data/lib/hyper_resource/modules/internal_attributes.rb +90 -0
- data/lib/hyper_resource/objects.rb +60 -0
- data/lib/hyper_resource/response.rb +2 -0
- data/lib/hyper_resource/version.rb +4 -0
- data/spec/aptible/resource/base_spec.rb +36 -0
- data/spec/aptible/resource/model_spec.rb +54 -0
- data/spec/fixtures/api.rb +11 -0
- data/spec/fixtures/mainframe.rb +5 -0
- data/spec/fixtures/token.rb +5 -0
- data/spec/shared/set_env.rb +10 -0
- data/spec/spec_helper.rb +14 -0
- metadata +225 -0
@@ -0,0 +1,90 @@
|
|
1
|
+
module HyperResource::Modules
|
2
|
+
module InternalAttributes
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
|
7
|
+
base._hr_class_attributes.each do |attr|
|
8
|
+
base._hr_class_attribute attr
|
9
|
+
end
|
10
|
+
|
11
|
+
(base._hr_attributes - base._hr_class_attributes).each do |attr|
|
12
|
+
base.send(:attr_accessor, attr)
|
13
|
+
end
|
14
|
+
|
15
|
+
## Fallback attributes fall back from instance to class.
|
16
|
+
(base._hr_attributes & base._hr_class_attributes).each do |attr|
|
17
|
+
base._hr_fallback_attribute attr
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module ClassMethods
|
22
|
+
|
23
|
+
def _hr_class_attributes # @private
|
24
|
+
[ :root, ## e.g. 'https://example.com/api/v1'
|
25
|
+
:auth, ## e.g. {:basic => ['username', 'password']}
|
26
|
+
:headers, ## e.g. {'Accept' => 'application/vnd.example+json'}
|
27
|
+
:namespace, ## e.g. 'ExampleAPI', or the class ExampleAPI itself
|
28
|
+
:adapter, ## subclass of HR::Adapter
|
29
|
+
:faraday_options ## e.g. {:request => {:timeout => 30}}
|
30
|
+
]
|
31
|
+
end
|
32
|
+
|
33
|
+
def _hr_attributes # @private
|
34
|
+
[ :root,
|
35
|
+
:href,
|
36
|
+
:auth,
|
37
|
+
:headers,
|
38
|
+
:namespace,
|
39
|
+
:adapter,
|
40
|
+
:faraday_options,
|
41
|
+
|
42
|
+
:request,
|
43
|
+
:response,
|
44
|
+
:body,
|
45
|
+
|
46
|
+
:attributes,
|
47
|
+
:links,
|
48
|
+
:objects,
|
49
|
+
|
50
|
+
:loaded
|
51
|
+
]
|
52
|
+
end
|
53
|
+
|
54
|
+
## Inheritable class attribute, kinda like in Rails.
|
55
|
+
def _hr_class_attribute(*names)
|
56
|
+
names.map(&:to_sym).each do |name|
|
57
|
+
instance_eval <<-EOT
|
58
|
+
def #{name}=(val)
|
59
|
+
@#{name} = val
|
60
|
+
end
|
61
|
+
def #{name}
|
62
|
+
return @#{name} if defined?(@#{name})
|
63
|
+
return superclass.#{name} if superclass.respond_to?(:#{name})
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
EOT
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
## Instance attributes which fall back to class attributes.
|
71
|
+
def _hr_fallback_attribute(*names)
|
72
|
+
names.map(&:to_sym).each do |name|
|
73
|
+
class_eval <<-EOT
|
74
|
+
def #{name}=(val)
|
75
|
+
@#{name} = val
|
76
|
+
end
|
77
|
+
def #{name}
|
78
|
+
return @#{name} if defined?(@#{name})
|
79
|
+
return self.class.#{name} if self.class.respond_to?(:#{name})
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
EOT
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end # ClassMethods
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
@@ -0,0 +1,60 @@
|
|
1
|
+
class HyperResource
|
2
|
+
class Objects < Hash
|
3
|
+
attr_accessor :_resource
|
4
|
+
|
5
|
+
def initialize(resource=nil)
|
6
|
+
self._resource = resource || HyperResource.new
|
7
|
+
end
|
8
|
+
|
9
|
+
## Creates accessor methods in self.class and self._resource.class.
|
10
|
+
## Protects against method creation into HyperResource::Objects and
|
11
|
+
## HyperResource classes. Just subclasses, please!
|
12
|
+
def _hr_create_methods!(opts={}) # @private
|
13
|
+
return if self.class.to_s == 'HyperResource::Objects'
|
14
|
+
return if self._resource.class.to_s == 'HyperResource'
|
15
|
+
return if self.class.send(
|
16
|
+
:class_variable_defined?, :@@_hr_created_objects_methods)
|
17
|
+
|
18
|
+
self.keys.each do |attr|
|
19
|
+
attr_sym = attr.to_sym
|
20
|
+
|
21
|
+
self.class.send(:define_method, attr_sym) do
|
22
|
+
self[attr]
|
23
|
+
end
|
24
|
+
|
25
|
+
## Don't stomp on _resource's methods
|
26
|
+
unless _resource.respond_to?(attr_sym)
|
27
|
+
_resource.class.send(:define_method, attr_sym) do
|
28
|
+
objects.send(attr_sym)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
self.class.send(:class_variable_set, :@@_hr_created_objects_methods, true)
|
34
|
+
end
|
35
|
+
|
36
|
+
def []=(attr, value) # @private
|
37
|
+
super(attr.to_s, value)
|
38
|
+
end
|
39
|
+
|
40
|
+
## When +key+ is a string, returns the array of objects under that name.
|
41
|
+
## When +key+ is a number, returns +ith(key)+. Returns nil on lookup
|
42
|
+
## failure.
|
43
|
+
def [](key)
|
44
|
+
case key
|
45
|
+
when String, Symbol
|
46
|
+
return super(key.to_s) if self.has_key?(key.to_s)
|
47
|
+
return super(key.to_sym) if self.has_key?(key.to_sym)
|
48
|
+
when Fixnum
|
49
|
+
return ith(key)
|
50
|
+
end
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
|
54
|
+
def method_missing(method, *args) # @private
|
55
|
+
return self[method] if self[method]
|
56
|
+
raise NoMethodError, "undefined method `#{method}' for #{self.inspect}"
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Aptible::Resource::Base do
|
4
|
+
subject { Api.new }
|
5
|
+
|
6
|
+
describe '#initialize' do
|
7
|
+
it 'should be a HyperResource instance' do
|
8
|
+
expect(subject).to be_a HyperResource
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should require root_url to be defined' do
|
12
|
+
expect { described_class.new }.to raise_error
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#bearer_token' do
|
17
|
+
it 'should accept an Aptible::Resource::Token' do
|
18
|
+
token = Api::Token.new
|
19
|
+
token.stub(:access_token) { 'aptible_auth_token' }
|
20
|
+
subject.stub(:token) { token }
|
21
|
+
expect(subject.bearer_token).to eq token.access_token
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should accept a Fridge::AccessToken' do
|
25
|
+
token = Fridge::AccessToken.new
|
26
|
+
token.stub(:to_s) { 'fridge_access_token' }
|
27
|
+
subject.stub(:token) { token }
|
28
|
+
expect(subject.bearer_token).to eq token.to_s
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should accept a String' do
|
32
|
+
subject.stub(:token) { 'token' }
|
33
|
+
expect(subject.bearer_token).to eq 'token'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Aptible::Resource::Model do
|
4
|
+
subject { Api.new }
|
5
|
+
|
6
|
+
describe '.collection_href' do
|
7
|
+
it 'should use the pluralized resource name' do
|
8
|
+
url = Api::Mainframe.collection_href
|
9
|
+
expect(url).to eq '/mainframes'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '.find' do
|
14
|
+
it 'should call find_by_url' do
|
15
|
+
url = '/mainframes/42'
|
16
|
+
expect(Api::Mainframe).to receive(:find_by_url).with url, {}
|
17
|
+
Api::Mainframe.find(42)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '.all' do
|
22
|
+
let(:mainframe) { double 'Mainframe' }
|
23
|
+
let(:collection) { double 'Api' }
|
24
|
+
|
25
|
+
before do
|
26
|
+
collection.stub(:mainframes) { [mainframe] }
|
27
|
+
Api::Mainframe.any_instance.stub(:find_by_url) { collection }
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should be an array' do
|
31
|
+
expect(Api::Mainframe.all).to be_a Array
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should return the root collection' do
|
35
|
+
expect(Api::Mainframe.all).to eq [mainframe]
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should pass options to the HyperResource initializer' do
|
39
|
+
klass = Api::Mainframe
|
40
|
+
options = { token: 'token' }
|
41
|
+
expect(klass).to receive(:new).with(options).and_return klass.new
|
42
|
+
Api::Mainframe.all(options)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '.create' do
|
47
|
+
it 'should create a new top-level resource' do
|
48
|
+
mainframes = double 'Api'
|
49
|
+
Api.stub_chain(:new, :mainframes) { mainframes }
|
50
|
+
expect(mainframes).to receive(:create).with(foo: 'bar')
|
51
|
+
Api::Mainframe.create(foo: 'bar')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
# Load shared spec files
|
5
|
+
Dir["#{File.dirname(__FILE__)}/shared/**/*.rb"].each do |file|
|
6
|
+
require file
|
7
|
+
end
|
8
|
+
# Load spec fixtures
|
9
|
+
Dir["#{File.dirname(__FILE__)}/fixtures/**/*.rb"].each do |file|
|
10
|
+
require file
|
11
|
+
end
|
12
|
+
|
13
|
+
# Require library up front
|
14
|
+
require 'aptible/resource'
|
metadata
ADDED
@@ -0,0 +1,225 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: aptible-resource
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Frank Macreery
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-04-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: uri_template
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.5.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.5.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faraday
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.8.6
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.8.6
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: json
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: fridge
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: activesupport
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: bundler
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.6'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ~>
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.6'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: aptible-tasks
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rake
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rspec
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ~>
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '2.0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ~>
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '2.0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: pry
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - '>='
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - '>='
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
description: Foundation classes for Aptible resource server gems
|
154
|
+
email:
|
155
|
+
- frank@macreery.com
|
156
|
+
executables: []
|
157
|
+
extensions: []
|
158
|
+
extra_rdoc_files: []
|
159
|
+
files:
|
160
|
+
- .gitignore
|
161
|
+
- .rspec
|
162
|
+
- .rubocop.yml
|
163
|
+
- .travis.yml
|
164
|
+
- Gemfile
|
165
|
+
- LICENSE.md
|
166
|
+
- README.md
|
167
|
+
- Rakefile
|
168
|
+
- aptible-resource.gemspec
|
169
|
+
- lib/aptible/resource.rb
|
170
|
+
- lib/aptible/resource/adapter.rb
|
171
|
+
- lib/aptible/resource/base.rb
|
172
|
+
- lib/aptible/resource/model.rb
|
173
|
+
- lib/aptible/resource/token.rb
|
174
|
+
- lib/aptible/resource/version.rb
|
175
|
+
- lib/hyper_resource.rb
|
176
|
+
- lib/hyper_resource/adapter.rb
|
177
|
+
- lib/hyper_resource/adapter/hal_json.rb
|
178
|
+
- lib/hyper_resource/attributes.rb
|
179
|
+
- lib/hyper_resource/exceptions.rb
|
180
|
+
- lib/hyper_resource/link.rb
|
181
|
+
- lib/hyper_resource/links.rb
|
182
|
+
- lib/hyper_resource/modules/http.rb
|
183
|
+
- lib/hyper_resource/modules/internal_attributes.rb
|
184
|
+
- lib/hyper_resource/objects.rb
|
185
|
+
- lib/hyper_resource/response.rb
|
186
|
+
- lib/hyper_resource/version.rb
|
187
|
+
- spec/aptible/resource/base_spec.rb
|
188
|
+
- spec/aptible/resource/model_spec.rb
|
189
|
+
- spec/fixtures/api.rb
|
190
|
+
- spec/fixtures/mainframe.rb
|
191
|
+
- spec/fixtures/token.rb
|
192
|
+
- spec/shared/set_env.rb
|
193
|
+
- spec/spec_helper.rb
|
194
|
+
homepage: https://github.com/aptible/aptible-resource
|
195
|
+
licenses:
|
196
|
+
- MIT
|
197
|
+
metadata: {}
|
198
|
+
post_install_message:
|
199
|
+
rdoc_options: []
|
200
|
+
require_paths:
|
201
|
+
- lib
|
202
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
203
|
+
requirements:
|
204
|
+
- - '>='
|
205
|
+
- !ruby/object:Gem::Version
|
206
|
+
version: '0'
|
207
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
208
|
+
requirements:
|
209
|
+
- - '>='
|
210
|
+
- !ruby/object:Gem::Version
|
211
|
+
version: '0'
|
212
|
+
requirements: []
|
213
|
+
rubyforge_project:
|
214
|
+
rubygems_version: 2.2.2
|
215
|
+
signing_key:
|
216
|
+
specification_version: 4
|
217
|
+
summary: Foundation classes for Aptible resource server gems
|
218
|
+
test_files:
|
219
|
+
- spec/aptible/resource/base_spec.rb
|
220
|
+
- spec/aptible/resource/model_spec.rb
|
221
|
+
- spec/fixtures/api.rb
|
222
|
+
- spec/fixtures/mainframe.rb
|
223
|
+
- spec/fixtures/token.rb
|
224
|
+
- spec/shared/set_env.rb
|
225
|
+
- spec/spec_helper.rb
|