resource_kit 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4dba252d8a80b4ce9ecf96972dada6a221824b05
4
- data.tar.gz: bb36d233fe0ae8e623b5f3c4c26a8a5dc74d2c81
3
+ metadata.gz: b5b4f9ef92b9859bec0fff18766087660f650fe1
4
+ data.tar.gz: 365c6e38731eae50c87eb11f7d225daa364e29de
5
5
  SHA512:
6
- metadata.gz: 63d61a484700d8bacf02569c3fe4c9cb5942f8cfc37e3fa3689b29a980e2726d0f2b190a2ea24cc9907e1b03a70be95f825ebf47c83cbdc40863b8656f435fcb
7
- data.tar.gz: 6f6b4d111147cf08a39c5a10a8114838cdffef0b45667e645690c5419f6b15ed2c5f96b353d35deda2fa386828f179514e530456ff08a4b7c06886af105fe957
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
- connection = Faraday.new(url: 'http://api.digitalocean.com') do |req|
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
- connection = Faraday.new(url: 'https://api.digitalocean.com', headers: { content_type: 'application/json', authorization: "Bearer #{token}" }) do |req|
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)
@@ -1,5 +1,4 @@
1
- require "resource_kit/version"
2
- require 'active_support/core_ext'
1
+ require 'resource_kit/version'
3
2
  require 'faraday'
4
3
 
5
4
  module ResourceKit
@@ -31,11 +31,13 @@ module ResourceKit
31
31
  end
32
32
 
33
33
  def handler(*response_codes, &block)
34
- response_codes.each do |code|
35
- unless code.is_a?(Fixnum)
36
- code = StatusCodeMapper.code_for(code)
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.in?(ALLOWED_VERBS)
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 action.verb.in?([:post, :put, :patch])
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(&:blank?).map do |piece|
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.to_query
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
- class_attribute :_resources
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.each do |code|
19
- unless code.is_a?(Fixnum)
20
- code = StatusCodeMapper.code_for(code)
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
@@ -1,3 +1,5 @@
1
+ require 'ostruct'
2
+
1
3
  module ResourceKit
2
4
  module Testing
3
5
  class ActionHandlerMatchers
@@ -31,4 +33,4 @@ module ResourceKit
31
33
  end
32
34
  end
33
35
  end
34
- end
36
+ end
@@ -1,3 +1,3 @@
1
1
  module ResourceKit
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -20,7 +20,6 @@ Gem::Specification.new do |spec|
20
20
  spec.require_paths = ["lib"]
21
21
 
22
22
  spec.add_dependency 'faraday'
23
- spec.add_dependency 'activesupport', '>= 3.0'
24
23
  spec.add_dependency 'addressable', '~> 2.3.6'
25
24
 
26
25
  spec.add_development_dependency "bundler", "~> 1.6"
@@ -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 { collection.default_handler(:ok, &handler) }
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.0
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-08-27 00:00:00.000000000 Z
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