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.
@@ -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,2 @@
1
+ class HyperResource::Response < Hash
2
+ end
@@ -0,0 +1,4 @@
1
+ class HyperResource
2
+ VERSION = '0.2.4'
3
+ VERSION_DATE = '2014-04-02'
4
+ 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
@@ -0,0 +1,11 @@
1
+ require 'aptible/resource'
2
+
3
+ class Api < Aptible::Resource::Base
4
+ def namespace
5
+ 'Api'
6
+ end
7
+
8
+ def root_url
9
+ 'https://resource.example.com'
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ require_relative 'api'
2
+
3
+ # rubocop:disable ClassAndModuleChildren
4
+ class Api::Mainframe < Api
5
+ end
@@ -0,0 +1,5 @@
1
+ require_relative 'api'
2
+
3
+ # rubocop:disable ClassAndModuleChildren
4
+ class Api::Token < Api
5
+ end
@@ -0,0 +1,10 @@
1
+ def set_env(*args, &block)
2
+ hash = args.first.is_a?(Hash) ? args.first : Hash[*args]
3
+ old_values = Hash[hash.map { |k, v| [k, ENV[k]] }]
4
+ begin
5
+ hash.each { |k, v| ENV[k] = v }
6
+ yield
7
+ ensure
8
+ old_values.each { |k, v| ENV[k] = v }
9
+ end
10
+ end
@@ -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