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 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