restfully 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
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