restfully 0.5.1 → 0.5.2

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.
data/CHANGELOG CHANGED
@@ -1,3 +1,13 @@
1
+ 0.5.2
2
+ * support for DELETE requests. Use resource.delete(options)
3
+ * fixed bug in resource.load(:reload => true)
4
+
5
+ 0.5.1
6
+ * fixed bug in resource.reload
7
+
8
+ 0.5.0
9
+ * support for POST requests. Use resource.submit(payload, options)
10
+
1
11
  0.4.1
2
12
  * added a require 'yaml' in restfully.rb (priteau);
3
13
  * added an introductory message when using the command-line tool;
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.1
1
+ 0.5.2
@@ -38,6 +38,12 @@ module Restfully
38
38
  super(property)
39
39
  end
40
40
  end
41
+
42
+ # Returns the current number of items (not the total number)
43
+ # in the collection.
44
+ def length
45
+ @items.length
46
+ end
41
47
 
42
48
  def populate_object(key, value)
43
49
  case key
@@ -68,12 +74,7 @@ module Restfully
68
74
  def inspect
69
75
  @items.inspect
70
76
  end
71
-
72
- # Returns the current number of items (not the total number)
73
- # in the collection.
74
- def length
75
- @items.length
76
- end
77
+
77
78
 
78
79
  def pretty_print(pp)
79
80
  super(pp) do |pp|
@@ -23,6 +23,13 @@ module Restfully
23
23
  end
24
24
  end # def get
25
25
 
26
+
27
+ def delete(request)
28
+ in_order_to_get_the_response_to(request) do |resource|
29
+ resource.delete(request.headers)
30
+ end
31
+ end # def delete
32
+
26
33
  def post(request)
27
34
  in_order_to_get_the_response_to(request) do |resource|
28
35
  resource.post(request.raw_body, request.headers)
@@ -52,6 +52,10 @@ module Restfully
52
52
  @properties[key]
53
53
  end
54
54
 
55
+ def respond_to?(method, *args)
56
+ @links.has_key?(method.to_s) || super(method, *args)
57
+ end
58
+
55
59
  def method_missing(method, *args)
56
60
  if link = @links[method.to_s]
57
61
  session.logger.debug "Loading link #{method}, args=#{args.inspect}"
@@ -77,7 +81,7 @@ module Restfully
77
81
  def load(options = {})
78
82
  options = options.symbolize_keys
79
83
  force_reload = !!options.delete(:reload)
80
- stale! unless (request = executed_requests['GET']) && request['options'] == options && request['body']
84
+ stale! unless !force_reload && (request = executed_requests['GET']) && request['options'] == options && request['body']
81
85
  if stale?
82
86
  reset
83
87
  if !force_reload && options[:body]
@@ -100,10 +104,17 @@ module Restfully
100
104
  end
101
105
  self
102
106
  end
107
+
108
+ # Convenience function to make a resource.load(:reload => true)
109
+ def reload
110
+ current_options = executed_requests['GET']['options'] rescue {}
111
+ stale!
112
+ self.load(current_options.merge(:reload => true))
113
+ end
103
114
 
104
115
  # == Description
105
116
  # Executes a POST request on the resource, reload it and returns self if successful.
106
- # If the response status is different than 2xx, raises a HTTP::ClientError or HTTP::ServerError.
117
+ # If the response status is different from 2xx, raises a HTTP::ClientError or HTTP::ServerError.
107
118
  # <tt>payload</tt>:: the input body of the request.
108
119
  # It may be a serialized string, or a ruby object
109
120
  # (that will be serialized according to the given or default content-type).
@@ -132,19 +143,27 @@ module Restfully
132
143
  end
133
144
  end
134
145
 
146
+ # == Description
147
+ # Executes a DELETE request on the resource, and returns true if successful.
148
+ # If the response status is different from 2xx or 3xx, raises an HTTP::ClientError or HTTP::ServerError.
149
+ # <tt>options</tt>:: list of options to pass to the request (see below)
150
+ # == Options
151
+ # <tt>:query</tt>:: a hash of query parameters to pass along the request.
152
+ # E.g. : resource.delete(:query => {:param1 => "value1"})
153
+ # <tt>:headers</tt>:: a hash of HTTP headers to pass along the request.
154
+ # E.g. : resource.delete(:headers => {:accept => 'application/json'})
155
+ def delete(options = {})
156
+ options = options.symbolize_keys
157
+ raise NotImplementedError, "The DELETE method is not allowed for this resource." unless http_methods.include?('DELETE')
158
+ response = session.delete(self.uri, options) # raises an exception if there is an error
159
+ stale!
160
+ (200..399).include?(response.status)
161
+ end
162
+
135
163
 
136
164
  def stale!; @status = :stale; end
137
165
  def stale?; @status == :stale; end
138
-
139
- def uri_for(path)
140
- uri.merge(URI.parse(path.to_s))
141
- end
142
-
143
- def reload
144
- current_options = executed_requests['GET']['options'] rescue {}
145
- stale!
146
- self.load(current_options.merge(:reload => true))
147
- end
166
+
148
167
 
149
168
  # == Description
150
169
  # Returns the list of allowed HTTP methods on the resource.
@@ -157,8 +176,8 @@ module Restfully
157
176
  (executed_requests['GET']['headers']['Allow'] || "GET").split(/,\s*/)
158
177
  end
159
178
 
160
- def respond_to?(method, *args)
161
- @links.has_key?(method.to_s) || super(method, *args)
179
+ def uri_for(path)
180
+ uri.merge(URI.parse(path.to_s))
162
181
  end
163
182
 
164
183
  def inspect(*args)
@@ -49,6 +49,12 @@ module Restfully
49
49
  transmit :post, HTTP::Request.new(uri_for(path), :body => body, :headers => options.delete(:headers), :query => options.delete(:query))
50
50
  end
51
51
 
52
+ # returns an HTTP::Response object or raise a Restfully::HTTP::Error
53
+ def delete(path, options = {})
54
+ options = options.symbolize_keys
55
+ transmit :delete, HTTP::Request.new(uri_for(path), :headers => options.delete(:headers), :query => options.delete(:query))
56
+ end
57
+
52
58
  # builds the complete URI, based on the given path and the session's base_uri
53
59
  def uri_for(path)
54
60
  URI.join(base_uri.to_s, path.to_s)
data/lib/restfully.rb CHANGED
@@ -14,7 +14,7 @@ require 'restfully/collection'
14
14
 
15
15
 
16
16
  module Restfully
17
- VERSION = "0.5.1"
17
+ VERSION = "0.5.2"
18
18
  class << self
19
19
  attr_accessor :adapter
20
20
  end
data/restfully.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{restfully}
8
- s.version = "0.5.1"
8
+ s.version = "0.5.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Cyril Rohr"]
12
- s.date = %q{2009-12-09}
12
+ s.date = %q{2009-12-14}
13
13
  s.default_executable = %q{restfully}
14
14
  s.description = %q{Experimental code for auto-generation of wrappers on top of RESTful APIs that follow HATEOAS principles and provide OPTIONS methods and/or Allow headers.}
15
15
  s.email = %q{cyril.rohr@gmail.com}
@@ -19,7 +19,7 @@ describe Restfully::HTTP::Adapters::RestClientAdapter do
19
19
  end
20
20
  it "should raise a not implemented error when trying to use functions not implemented yet" do
21
21
  adapter = Restfully::HTTP::Adapters::RestClientAdapter.new("https://api.grid5000.fr")
22
- lambda{adapter.delete(mock("restfully request"))}.should raise_error NotImplementedError, "DELETE is not supported by your adapter."
22
+ lambda{adapter.put(mock("restfully request"))}.should raise_error NotImplementedError, "PUT is not supported by your adapter."
23
23
  end
24
24
  it "should rescue any RestClient::Exception and correctly populate the response" do
25
25
  res = mock(Net::HTTPResponse, :code => 404, :body => '{"message":"whatever"}', :to_hash => {'Content-Type' => 'application/json;charset=utf-8', 'Content-Length' => 22}, :[] => '')
@@ -9,15 +9,16 @@ describe Resource do
9
9
  end
10
10
 
11
11
  describe "accessors" do
12
+ before(:each) do
13
+ @resource = Resource.new(@uri, @session=mock("session"))
14
+ end
12
15
  it "should have a reader on the session" do
13
- resource = Resource.new("uri", session=mock("session"))
14
- resource.should_not respond_to(:session=)
15
- resource.session.should == session
16
+ @resource.should_not respond_to(:session=)
17
+ @resource.session.should == @session
16
18
  end
17
19
  it "should have a reader on the uri" do
18
- resource = Resource.new("uri", session=mock("session"))
19
- resource.should_not respond_to(:uri=)
20
- resource.uri.should == URI.parse("uri")
20
+ @resource.should_not respond_to(:uri=)
21
+ @resource.uri.should == @uri
21
22
  end
22
23
  end
23
24
 
@@ -177,11 +178,21 @@ describe Resource do
177
178
  resource.links.keys.should =~ ['versions', 'clusters', 'environments', 'status', 'parent', 'version']
178
179
  end
179
180
 
180
- it "should reload the resource if user forces reload" do
181
+ it "should reload the resource if user forces reload [first loading]" do
181
182
  resource = Resource.new(@uri, session = mock("session"))
182
183
  session.should_receive(:get).and_return(response = mock("response", :headers => {}, :body => {}))
183
184
  resource.load(:reload => true, :body => mock("body"))
184
185
  end
186
+ it "should reload the resource when user forces reload [has been loaded at least once before]" do
187
+ resource = Resource.new(@uri, session = mock("session"))
188
+ resource.instance_variable_set "@status", :loaded
189
+ resource.should_not be_stale
190
+ resource.should_receive(:executed_requests).at_least(1).and_return({
191
+ 'GET' => {'options' => {:query => {:q=>1}}, 'body' => {'a' => 'b'}}
192
+ })
193
+ session.should_receive(:get).and_return(response = mock("response", :headers => {}, :body => {}))
194
+ resource.load(:reload => true, :query => {:q => 1})
195
+ end
185
196
  end
186
197
 
187
198
 
@@ -241,4 +252,19 @@ describe Resource do
241
252
  @resource.submit("whatever").should == @resource
242
253
  end
243
254
  end
255
+
256
+ describe "deleting" do
257
+ before do
258
+ @resource = Resource.new(@uri, @session = mock("session", :logger => @logger))
259
+ @resource.stub!(:http_methods).and_return(['GET', 'DELETE'])
260
+ end
261
+ it "should raise an error if the DELETE method is not supported by the service" do
262
+ @resource.stub!(:http_methods).and_return(['GET'])
263
+ lambda{@resource.delete}.should raise_error(NotImplementedError, /DELETE method is not allowed/)
264
+ end
265
+ it "should send a DELETE request to the resource URI" do
266
+ @session.should_receive(:delete).with(@uri, :query => {:q => 'v'}, :headers => {'Accept' => 'application/json'}).and_return(response = mock("http response", :status => 204))
267
+ @resource.delete(:query => {:q => 'v'}, :headers => {'Accept' => 'application/json'}).should be_true
268
+ end
269
+ end
244
270
  end
data/spec/session_spec.rb CHANGED
@@ -153,4 +153,12 @@ describe Session do
153
153
  end
154
154
  end
155
155
 
156
+ describe "DELETEing resources" do
157
+ it "should create a new Request object and transmit it" do
158
+ Restfully::HTTP::Request.should_receive(:new).with(URI.parse('https://api.grid5000.fr/sid/some/path'), :headers => {:accept => 'application/json'}, :query => nil).and_return(@request)
159
+ @session.should_receive(:transmit).with(:delete, @request)
160
+ @session.delete('some/path', 'headers' => {:accept => 'application/json'})
161
+ end
162
+ end
163
+
156
164
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: restfully
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cyril Rohr
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-09 00:00:00 +01:00
12
+ date: 2009-12-14 00:00:00 +01:00
13
13
  default_executable: restfully
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency