resource_kit 0.1.0 → 0.1.1
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/README.md +16 -3
- data/examples/digitalocean_droplets.rb +3 -3
- data/examples/httpbin_client.rb +15 -0
- data/lib/resource_kit.rb +1 -2
- data/lib/resource_kit/action.rb +7 -5
- data/lib/resource_kit/action_invoker.rb +4 -4
- data/lib/resource_kit/endpoint_resolver.rb +6 -4
- data/lib/resource_kit/inheritable_attribute.rb +20 -0
- data/lib/resource_kit/resource.rb +11 -2
- data/lib/resource_kit/resource_collection.rb +14 -5
- data/lib/resource_kit/testing/action_handler_matchers.rb +3 -1
- data/lib/resource_kit/version.rb +1 -1
- data/resource_kit.gemspec +0 -1
- data/spec/lib/resource_kit/action_invoker_spec.rb +10 -1
- data/spec/lib/resource_kit/inheritable_attribute_spec.rb +54 -0
- data/spec/lib/resource_kit/resource_collection_spec.rb +14 -2
- data/spec/lib/resource_kit/resource_spec.rb +2 -1
- metadata +6 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b5b4f9ef92b9859bec0fff18766087660f650fe1
|
4
|
+
data.tar.gz: 365c6e38731eae50c87eb11f7d225daa364e29de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc1e6f8e169f2bf93da9e32019a525ac8374bda740266a482d95164456315a4495160ca5715761a0d978ea2f1ab5577b93a7f3ce7037c1c9442540afab59299d
|
7
|
+
data.tar.gz: f06860e9f4bf4789bfd7865c61e2977239f73d9a69f1cd7f2933381f0a8d9ce80c36957ddcb7e8d40ac335dd3438d18a50dc60a28e6d3604f3c28461eaaea69e
|
data/README.md
CHANGED
@@ -33,6 +33,7 @@ class DropletResource < ResourceKit::Resource
|
|
33
33
|
resources do
|
34
34
|
default_handler(422) { |response| ErrorMapping.extract_single(response.body, :read) }
|
35
35
|
default_handler(:ok, :created) { |response| DropletMapping.extract_single(response.body, :read) }
|
36
|
+
default_handler { |response| raise "Unexpected response status #{response.status}... #{response.body}" }
|
36
37
|
|
37
38
|
# Defining actions will create instance methods on the resource class to call them.
|
38
39
|
action :find do
|
@@ -68,14 +69,26 @@ class DropletResource < ResourceKit::Resource
|
|
68
69
|
end
|
69
70
|
```
|
70
71
|
|
72
|
+
Instead of using `#action`, you can use any of the supported HTTP verb methods including `#get`, `#post`, `#put`, `#delete`, `#head`, `#patch`, and `#options`. Thus, the above example can be also written as:
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
class DropletResource < ResourceKit::Resource
|
76
|
+
resources do
|
77
|
+
get :all, '/v2/droplets' do
|
78
|
+
handler(:ok) { |response| DropletMapping.extract_collection(response.body, :read) }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
71
84
|
Now that we've described our resources. We can instantiate our class with a connection object. ResourceKit relies on the interface that Faraday provides. For example:
|
72
85
|
|
73
86
|
```ruby
|
74
|
-
|
87
|
+
conn = Faraday.new(url: 'http://api.digitalocean.com') do |req|
|
75
88
|
req.adapter :net_http
|
76
89
|
end
|
77
90
|
|
78
|
-
resource = DropletResource.new(connection)
|
91
|
+
resource = DropletResource.new(connection: conn)
|
79
92
|
```
|
80
93
|
|
81
94
|
Now that we've instantiated a resource with our class, we can call the actions we've defined on it.
|
@@ -107,7 +120,7 @@ class CommentResource < ResourceKit::Resource
|
|
107
120
|
end
|
108
121
|
|
109
122
|
user = User.find(123)
|
110
|
-
resource = CommentResource.new(connection, user)
|
123
|
+
resource = CommentResource.new(connection: conn, scope: user)
|
111
124
|
comments = resource.all #=> Will fetch from /users/123/comments
|
112
125
|
```
|
113
126
|
|
@@ -43,11 +43,11 @@ class DropletResource < ResourceKit::Resource
|
|
43
43
|
end
|
44
44
|
|
45
45
|
token = 'YOUR_ACCESS_TOKEN'
|
46
|
-
|
46
|
+
conn = Faraday.new(url: 'https://api.digitalocean.com', headers: { content_type: 'application/json', authorization: "Bearer #{token}" }) do |req|
|
47
47
|
req.adapter :net_http
|
48
48
|
end
|
49
49
|
|
50
|
-
resource = DropletResource.new(connection)
|
50
|
+
resource = DropletResource.new(connection: conn)
|
51
51
|
|
52
52
|
# Retrieve all droplets
|
53
|
-
puts resource.all
|
53
|
+
puts resource.all
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'resource_kit'
|
2
|
+
|
3
|
+
class HTTPBinResource < ResourceKit::Resource
|
4
|
+
resources do
|
5
|
+
get '/ip' => :ip
|
6
|
+
get '/status/:code' => :status
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
conn = Faraday.new(url: 'http://httpbin.org')
|
11
|
+
resource = HTTPBinResource.new(connection: conn)
|
12
|
+
|
13
|
+
puts resource.ip
|
14
|
+
puts
|
15
|
+
puts resource.status(code: 418)
|
data/lib/resource_kit.rb
CHANGED
data/lib/resource_kit/action.rb
CHANGED
@@ -31,11 +31,13 @@ module ResourceKit
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def handler(*response_codes, &block)
|
34
|
-
response_codes.
|
35
|
-
|
36
|
-
|
34
|
+
if response_codes.empty?
|
35
|
+
handlers[:any] = block
|
36
|
+
else
|
37
|
+
response_codes.each do |code|
|
38
|
+
code = StatusCodeMapper.code_for(code) unless code.is_a?(Fixnum)
|
39
|
+
handlers[code] = block
|
37
40
|
end
|
38
|
-
handlers[code] = block
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|
@@ -61,4 +63,4 @@ module ResourceKit
|
|
61
63
|
nil
|
62
64
|
end
|
63
65
|
end
|
64
|
-
end
|
66
|
+
end
|
@@ -15,7 +15,7 @@ module ResourceKit
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def handle_response
|
18
|
-
if handler = action.handlers[response.status]
|
18
|
+
if handler = action.handlers[response.status] || action.handlers[:any]
|
19
19
|
resource.instance_exec(response, &handler)
|
20
20
|
else
|
21
21
|
response.body
|
@@ -29,10 +29,10 @@ module ResourceKit
|
|
29
29
|
def response
|
30
30
|
return @response if @response
|
31
31
|
|
32
|
-
raise ArgumentError, "Verb '#{action.verb}' is not allowed" unless action.verb
|
32
|
+
raise ArgumentError, "Verb '#{action.verb}' is not allowed" unless ALLOWED_VERBS.include?(action.verb)
|
33
33
|
|
34
34
|
@response = connection.send(action.verb, resolver.resolve(options)) do |request|
|
35
|
-
request.body = construct_body if action.body and
|
35
|
+
request.body = construct_body if action.body and [:post, :put, :patch].include?(action.verb)
|
36
36
|
append_hooks(:before, request)
|
37
37
|
end
|
38
38
|
end
|
@@ -55,4 +55,4 @@ module ResourceKit
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
58
|
-
end
|
58
|
+
end
|
@@ -27,16 +27,18 @@ module ResourceKit
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def normalized_path_components(*components)
|
30
|
-
components.reject(&:
|
30
|
+
components.reject(&:empty?).map do |piece|
|
31
31
|
# Remove leading and trailing forward slashes
|
32
32
|
piece.gsub(/(^\/)|(\/$)/, '')
|
33
33
|
end.join('/').insert(0, '/')
|
34
34
|
end
|
35
35
|
|
36
36
|
def append_query_values(uri, values)
|
37
|
-
query_param_keys.each_with_object({}) do |key, query_values|
|
37
|
+
params = query_param_keys.each_with_object({}) do |key, query_values|
|
38
38
|
query_values[key] = values[key] if values.has_key?(key)
|
39
|
-
end
|
39
|
+
end
|
40
|
+
|
41
|
+
URI.encode_www_form(params)
|
40
42
|
end
|
41
43
|
end
|
42
|
-
end
|
44
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module ResourceKit
|
2
|
+
module InheritableAttribute
|
3
|
+
def inheritable_attr(name)
|
4
|
+
instance_eval <<-RUBY
|
5
|
+
def #{name}=(v)
|
6
|
+
@#{name} = v
|
7
|
+
end
|
8
|
+
|
9
|
+
def #{name}
|
10
|
+
@#{name} ||= InheritableAttribute.inherit(self, :#{name})
|
11
|
+
end
|
12
|
+
RUBY
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.inherit(klass, name)
|
16
|
+
return unless klass.superclass.respond_to?(name) and value = klass.superclass.send(name)
|
17
|
+
value.clone
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,6 +1,9 @@
|
|
1
|
+
require 'resource_kit/inheritable_attribute'
|
2
|
+
|
1
3
|
module ResourceKit
|
2
4
|
class Resource
|
3
|
-
|
5
|
+
extend InheritableAttribute
|
6
|
+
inheritable_attr :_resources
|
4
7
|
|
5
8
|
attr_reader :connection, :scope
|
6
9
|
|
@@ -27,5 +30,11 @@ module ResourceKit
|
|
27
30
|
def action_and_connection(action_name)
|
28
31
|
ActionConnection.new(action(action_name), connection)
|
29
32
|
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def _resources
|
37
|
+
self.class._resources
|
38
|
+
end
|
30
39
|
end
|
31
|
-
end
|
40
|
+
end
|
@@ -14,12 +14,21 @@ module ResourceKit
|
|
14
14
|
action.tap { |a| self << a }
|
15
15
|
end
|
16
16
|
|
17
|
+
ResourceKit::ALLOWED_VERBS.each do |verb|
|
18
|
+
define_method verb do |path_name, &block|
|
19
|
+
path, name = path_name.to_a.flatten
|
20
|
+
action(name, "#{verb.upcase} #{path}", &block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
17
24
|
def default_handler(*response_codes, &block)
|
18
|
-
response_codes.
|
19
|
-
|
20
|
-
|
25
|
+
if response_codes.empty?
|
26
|
+
default_handlers[:any] = block
|
27
|
+
else
|
28
|
+
response_codes.each do |code|
|
29
|
+
code = StatusCodeMapper.code_for(code) unless code.is_a?(Fixnum)
|
30
|
+
default_handlers[code] = block
|
21
31
|
end
|
22
|
-
default_handlers[code] = block
|
23
32
|
end
|
24
33
|
end
|
25
34
|
|
@@ -43,4 +52,4 @@ module ResourceKit
|
|
43
52
|
return matched[:verb], matched[:path]
|
44
53
|
end
|
45
54
|
end
|
46
|
-
end
|
55
|
+
end
|
data/lib/resource_kit/version.rb
CHANGED
data/resource_kit.gemspec
CHANGED
@@ -60,6 +60,15 @@ RSpec.describe ResourceKit::ActionInvoker do
|
|
60
60
|
result = ResourceKit::ActionInvoker.call(action, resource)
|
61
61
|
expect(result).to eq('404ed')
|
62
62
|
end
|
63
|
+
|
64
|
+
it 'uses a default handler if provided' do
|
65
|
+
action.verb :get
|
66
|
+
action.path '/users'
|
67
|
+
action.handler { |response| 'Something unexpected happened.' }
|
68
|
+
|
69
|
+
result = ResourceKit::ActionInvoker.call(action, resource)
|
70
|
+
expect(result).to eq('Something unexpected happened.')
|
71
|
+
end
|
63
72
|
end
|
64
73
|
|
65
74
|
context 'for requests with bodies' do
|
@@ -144,4 +153,4 @@ RSpec.describe ResourceKit::ActionInvoker do
|
|
144
153
|
end
|
145
154
|
end
|
146
155
|
end
|
147
|
-
end
|
156
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ResourceKit::InheritableAttribute do
|
4
|
+
subject do
|
5
|
+
Class.new(Object) do
|
6
|
+
extend ResourceKit::InheritableAttribute
|
7
|
+
|
8
|
+
inheritable_attr :_resources
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'provides a reader with an empty inherited attribute' do
|
13
|
+
expect(subject._resources).to be_nil
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'provides a reader with empty inherited attributes in a derived class' do
|
17
|
+
expect(Class.new(subject)._resources).to be_nil
|
18
|
+
|
19
|
+
# subject._resouces = true
|
20
|
+
# Class.new(subject)._resources # TODO: crashes.
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'provides an attribute copy in subclasses' do
|
24
|
+
subject._resources = []
|
25
|
+
expect(subject._resources.object_id).not_to eq Class.new(subject)._resources.object_id
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'provides a writer' do
|
29
|
+
subject._resources = [:resource]
|
30
|
+
expect(subject._resources).to eq [:resource]
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'inherits attributes' do
|
34
|
+
subject._resources = [:resource]
|
35
|
+
|
36
|
+
subclass_a = Class.new(subject)
|
37
|
+
subclass_a._resources << :another_resource
|
38
|
+
|
39
|
+
subclass_b = Class.new(subject)
|
40
|
+
subclass_b._resources << :different_resource
|
41
|
+
|
42
|
+
expect(subject._resources).to eq [:resource]
|
43
|
+
expect(subclass_a._resources).to eq [:resource, :another_resource]
|
44
|
+
expect(subclass_b._resources).to eq [:resource, :different_resource]
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'does not inherit attributes if we set explicitely' do
|
48
|
+
subject._resources = [:resource]
|
49
|
+
subclass = Class.new(subject)
|
50
|
+
|
51
|
+
subclass._resources = [:another_resource]
|
52
|
+
expect(subclass._resources).to eq [:another_resource]
|
53
|
+
end
|
54
|
+
end
|
@@ -11,6 +11,13 @@ RSpec.describe ResourceKit::ResourceCollection do
|
|
11
11
|
expect(collection.default_handlers[200]).to eq(handler_block)
|
12
12
|
expect(collection.default_handlers[204]).to eq(handler_block)
|
13
13
|
end
|
14
|
+
|
15
|
+
it 'provides a top-level default handler if no status code is provided' do
|
16
|
+
handler_block = Proc.new { true }
|
17
|
+
collection.default_handler(&handler_block)
|
18
|
+
|
19
|
+
expect(collection.default_handlers[:any]).to eq(handler_block)
|
20
|
+
end
|
14
21
|
end
|
15
22
|
|
16
23
|
describe '#action' do
|
@@ -32,12 +39,17 @@ RSpec.describe ResourceKit::ResourceCollection do
|
|
32
39
|
|
33
40
|
context 'when default handlers have been specified on the collection' do
|
34
41
|
let(:handler) { Proc.new { |response| 'sure' } }
|
42
|
+
let(:default_handler) { Proc.new { 'Something unexpected happened!' } }
|
35
43
|
|
36
|
-
before
|
44
|
+
before do
|
45
|
+
collection.default_handler(:ok, &handler)
|
46
|
+
collection.default_handler(&default_handler)
|
47
|
+
end
|
37
48
|
|
38
49
|
it 'prepends the default handlers to the test' do
|
39
50
|
action = collection.action(:all)
|
40
51
|
expect(action.handlers[200]).to eq(handler)
|
52
|
+
expect(action.handlers[:any]).to eq(default_handler)
|
41
53
|
end
|
42
54
|
end
|
43
55
|
end
|
@@ -52,4 +64,4 @@ RSpec.describe ResourceKit::ResourceCollection do
|
|
52
64
|
expect(retrieved_action.name).to eq(:all)
|
53
65
|
end
|
54
66
|
end
|
55
|
-
end
|
67
|
+
end
|
@@ -24,6 +24,7 @@ RSpec.describe ResourceKit::Resource do
|
|
24
24
|
|
25
25
|
it "defines the action method" do
|
26
26
|
expect(droplet_resource).to respond_to(:find)
|
27
|
+
expect(droplet_resource).to respond_to(:all)
|
27
28
|
end
|
28
29
|
end
|
29
30
|
end
|
@@ -62,4 +63,4 @@ RSpec.describe ResourceKit::Resource do
|
|
62
63
|
expect(instance.action(:find)).to be_kind_of(ResourceKit::Action)
|
63
64
|
end
|
64
65
|
end
|
65
|
-
end
|
66
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resource_kit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Ross
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-10-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: faraday
|
@@ -25,20 +25,6 @@ dependencies:
|
|
25
25
|
- - ">="
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '0'
|
28
|
-
- !ruby/object:Gem::Dependency
|
29
|
-
name: activesupport
|
30
|
-
requirement: !ruby/object:Gem::Requirement
|
31
|
-
requirements:
|
32
|
-
- - ">="
|
33
|
-
- !ruby/object:Gem::Version
|
34
|
-
version: '3.0'
|
35
|
-
type: :runtime
|
36
|
-
prerelease: false
|
37
|
-
version_requirements: !ruby/object:Gem::Requirement
|
38
|
-
requirements:
|
39
|
-
- - ">="
|
40
|
-
- !ruby/object:Gem::Version
|
41
|
-
version: '3.0'
|
42
28
|
- !ruby/object:Gem::Dependency
|
43
29
|
name: addressable
|
44
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -152,10 +138,12 @@ files:
|
|
152
138
|
- README.md
|
153
139
|
- Rakefile
|
154
140
|
- examples/digitalocean_droplets.rb
|
141
|
+
- examples/httpbin_client.rb
|
155
142
|
- lib/resource_kit.rb
|
156
143
|
- lib/resource_kit/action.rb
|
157
144
|
- lib/resource_kit/action_invoker.rb
|
158
145
|
- lib/resource_kit/endpoint_resolver.rb
|
146
|
+
- lib/resource_kit/inheritable_attribute.rb
|
159
147
|
- lib/resource_kit/method_factory.rb
|
160
148
|
- lib/resource_kit/resource.rb
|
161
149
|
- lib/resource_kit/resource_collection.rb
|
@@ -169,6 +157,7 @@ files:
|
|
169
157
|
- spec/lib/resource_kit/action_invoker_spec.rb
|
170
158
|
- spec/lib/resource_kit/action_spec.rb
|
171
159
|
- spec/lib/resource_kit/endpoint_resolver_spec.rb
|
160
|
+
- spec/lib/resource_kit/inheritable_attribute_spec.rb
|
172
161
|
- spec/lib/resource_kit/method_factory_spec.rb
|
173
162
|
- spec/lib/resource_kit/resource_collection_spec.rb
|
174
163
|
- spec/lib/resource_kit/resource_spec.rb
|
@@ -206,6 +195,7 @@ test_files:
|
|
206
195
|
- spec/lib/resource_kit/action_invoker_spec.rb
|
207
196
|
- spec/lib/resource_kit/action_spec.rb
|
208
197
|
- spec/lib/resource_kit/endpoint_resolver_spec.rb
|
198
|
+
- spec/lib/resource_kit/inheritable_attribute_spec.rb
|
209
199
|
- spec/lib/resource_kit/method_factory_spec.rb
|
210
200
|
- spec/lib/resource_kit/resource_collection_spec.rb
|
211
201
|
- spec/lib/resource_kit/resource_spec.rb
|