restfully 0.5.10 → 0.6.0
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 +5 -0
- data/VERSION +1 -1
- data/lib/restfully.rb +2 -3
- data/lib/restfully/collection.rb +5 -2
- data/lib/restfully/extensions.rb +25 -15
- data/lib/restfully/http/request.rb +2 -1
- data/lib/restfully/link.rb +1 -1
- data/restfully.gemspec +3 -3
- data/spec/collection_spec.rb +2 -2
- data/spec/http/request_spec.rb +2 -2
- data/spec/spec_helper.rb +4 -2
- metadata +51 -29
data/CHANGELOG
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
0.6.0
|
2
|
+
* Fixed collection traversal.
|
3
|
+
* Query parameters that are Arrays are no longer joined.
|
4
|
+
* Added 'next' as valid link relationship.
|
5
|
+
|
1
6
|
0.5.10
|
2
7
|
* Direct lookup to the resource if it cannot be found in the collection (for APIs that do not return all the items in a collection) (priteau)
|
3
8
|
* Automatically load next pages of a collection when iterating through it
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.6.0
|
data/lib/restfully.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'backports'
|
2
2
|
require 'yaml'
|
3
|
+
require 'restfully/extensions'
|
3
4
|
require 'restfully/error'
|
4
5
|
require 'restfully/parsing'
|
5
6
|
require 'restfully/http'
|
6
7
|
require 'restfully/http/adapters/rest_client_adapter'
|
7
|
-
require 'restfully/extensions'
|
8
8
|
require 'restfully/session'
|
9
9
|
require 'restfully/special_hash'
|
10
10
|
require 'restfully/special_array'
|
@@ -12,9 +12,8 @@ require 'restfully/link'
|
|
12
12
|
require 'restfully/resource'
|
13
13
|
require 'restfully/collection'
|
14
14
|
|
15
|
-
|
16
15
|
module Restfully
|
17
|
-
VERSION = "0.
|
16
|
+
VERSION = "0.6.0"
|
18
17
|
class << self
|
19
18
|
attr_accessor :adapter
|
20
19
|
end
|
data/lib/restfully/collection.rb
CHANGED
@@ -28,9 +28,12 @@ module Restfully
|
|
28
28
|
def each(*args, &block)
|
29
29
|
@items.each_index{ |i|
|
30
30
|
block.call(@items[i])
|
31
|
-
if i == @items.length-1 && @items.length < self["total"]
|
31
|
+
if i == @items.length-1 && @items.length+self["offset"] < self["total"]
|
32
32
|
# load next page
|
33
|
-
|
33
|
+
query_options = executed_requests['GET']['options'][:query] || {}
|
34
|
+
query_options[:offset] = self["offset"]+@items.length
|
35
|
+
query_options[:limit] ||= 200
|
36
|
+
next_page = Collection.new(uri, session).load(:query => query_options) rescue nil
|
34
37
|
if next_page && next_page['offset'] != self["offset"]
|
35
38
|
@items.push(*next_page.to_a)
|
36
39
|
end
|
data/lib/restfully/extensions.rb
CHANGED
@@ -2,23 +2,33 @@ class BasicObject #:nodoc:
|
|
2
2
|
instance_methods.each { |m| undef_method m unless m =~ /^__|instance_eval/ }
|
3
3
|
end unless defined?(BasicObject)
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
class Object
|
6
|
+
# Taken from ActiveSupport
|
7
|
+
def to_query(key)
|
8
|
+
require 'cgi' unless defined?(CGI) && defined?(CGI::escape)
|
9
|
+
"#{CGI.escape(key.to_s)}=#{CGI.escape(to_params.to_s)}"
|
10
|
+
end
|
11
|
+
|
9
12
|
def to_params
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
if v.is_a?(Array)
|
14
|
-
params << "#{k}=#{v.join(",")}&"
|
15
|
-
else
|
16
|
-
params << "#{k}=#{v.to_s}&"
|
17
|
-
end
|
18
|
-
end
|
13
|
+
to_s
|
14
|
+
end
|
15
|
+
end
|
19
16
|
|
20
|
-
|
21
|
-
|
17
|
+
class Hash
|
18
|
+
# Converts a hash into a string suitable for use as a URL query string.
|
19
|
+
# An optional <tt>namespace</tt> can be passed to enclose the param names.
|
20
|
+
# Taken from ActiveSupport
|
21
|
+
def to_params(namespace = nil)
|
22
|
+
collect do |key, value|
|
23
|
+
value.to_query(namespace ? "#{namespace}[#{key}]" : key)
|
24
|
+
end * '&'
|
22
25
|
end
|
26
|
+
end
|
23
27
|
|
28
|
+
class Array
|
29
|
+
# Taken from ActiveSupport
|
30
|
+
def to_query(key)
|
31
|
+
prefix = "#{key}[]"
|
32
|
+
collect { |value| value.to_query(prefix) }.join '&'
|
33
|
+
end
|
24
34
|
end
|
@@ -1,10 +1,12 @@
|
|
1
1
|
require 'uri'
|
2
2
|
module Restfully
|
3
3
|
module HTTP
|
4
|
+
|
4
5
|
class Request
|
5
6
|
include Headers, Restfully::Parsing
|
6
7
|
attr_reader :headers, :uri
|
7
8
|
attr_accessor :retries
|
9
|
+
|
8
10
|
def initialize(url, options = {})
|
9
11
|
options = options.symbolize_keys
|
10
12
|
@uri = url.kind_of?(URI) ? url : URI.parse(url)
|
@@ -16,7 +18,6 @@ module Restfully
|
|
16
18
|
@retries = 0
|
17
19
|
end
|
18
20
|
|
19
|
-
|
20
21
|
def body
|
21
22
|
if @body.kind_of?(String)
|
22
23
|
@unserialized_body ||= unserialize(@body, :content_type => @headers['Content-Type'])
|
data/lib/restfully/link.rb
CHANGED
@@ -2,7 +2,7 @@ require 'uri'
|
|
2
2
|
module Restfully
|
3
3
|
class Link
|
4
4
|
|
5
|
-
VALID_RELATIONSHIPS = %w{member parent collection self alternate}
|
5
|
+
VALID_RELATIONSHIPS = %w{member parent collection self alternate next}
|
6
6
|
RELATIONSHIPS_REQUIRING_TITLE = %w{collection member}
|
7
7
|
|
8
8
|
attr_reader :rel, :title, :href, :errors
|
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.
|
8
|
+
s.version = "0.6.0"
|
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{
|
12
|
+
s.date = %q{2011-01-18}
|
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}
|
@@ -67,7 +67,7 @@ Gem::Specification.new do |s|
|
|
67
67
|
s.homepage = %q{http://github.com/crohr/restfully}
|
68
68
|
s.rdoc_options = ["--charset=UTF-8"]
|
69
69
|
s.require_paths = ["lib"]
|
70
|
-
s.rubygems_version = %q{1.3.
|
70
|
+
s.rubygems_version = %q{1.3.6}
|
71
71
|
s.summary = %q{Experimental code for auto-generation of wrappers on top of RESTful APIs that follow some specific conventions.}
|
72
72
|
s.test_files = [
|
73
73
|
"spec/collection_spec.rb",
|
data/spec/collection_spec.rb
CHANGED
@@ -48,8 +48,8 @@ describe Collection do
|
|
48
48
|
body2["offset"] = 16
|
49
49
|
body2["items"][1]["uid"] = "18th item"
|
50
50
|
collection = Collection.new(@uri, session = mock('session')).load(:body => body)
|
51
|
-
session.should_receive(:get).with(@uri, :query => {:offset => 8}).ordered.and_return(response = mock("response", :body => body1, :status => 200, :headers => {}))
|
52
|
-
session.should_receive(:get).with(@uri, :query => {:offset => 16}).ordered.and_return(response = mock("response", :body => body2, :status => 200, :headers => {}))
|
51
|
+
session.should_receive(:get).with(@uri, :query => {:offset => 8, :limit => 200}).ordered.and_return(response = mock("response", :body => body1, :status => 200, :headers => {}))
|
52
|
+
session.should_receive(:get).with(@uri, :query => {:offset => 16, :limit => 200}).ordered.and_return(response = mock("response", :body => body2, :status => 200, :headers => {}))
|
53
53
|
collection.find{|item| item["uid"] == "18th item"}.should_not be_nil
|
54
54
|
end
|
55
55
|
it "should always return nil if the searched item is not in the collection" do
|
data/spec/http/request_spec.rb
CHANGED
@@ -9,8 +9,8 @@ describe Restfully::HTTP::Request do
|
|
9
9
|
:body => {"key" => "value"}.to_json
|
10
10
|
)
|
11
11
|
request.uri.should be_a URI
|
12
|
-
request.uri.to_s.should == 'https://api.grid5000.fr/sid/grid5000?q1=v1&q2=v2&custom_param1=3
|
13
|
-
request.uri.query.should == "q1=v1&q2=v2&custom_param1=3
|
12
|
+
request.uri.to_s.should == 'https://api.grid5000.fr/sid/grid5000?q1=v1&q2=v2&custom_param1%5B%5D=3&custom_param1%5B%5D=4&custom_param1%5B%5D=5&custom_param1%5B%5D=6&custom_param2=value_custom_param2'
|
13
|
+
request.uri.query.should == "q1=v1&q2=v2&custom_param1%5B%5D=3&custom_param1%5B%5D=4&custom_param1%5B%5D=5&custom_param1%5B%5D=6&custom_param2=value_custom_param2"
|
14
14
|
request.headers.should == {
|
15
15
|
"Content-Type"=>"application/json",
|
16
16
|
'Accept' => 'application/xml',
|
data/spec/spec_helper.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
2
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
|
4
|
+
require 'webmock/rspec'
|
5
|
+
include WebMock
|
6
|
+
|
3
7
|
require 'restfully'
|
4
8
|
require 'spec'
|
5
9
|
require 'spec/autorun'
|
6
10
|
require 'json'
|
7
11
|
|
8
|
-
require 'webmock/rspec'
|
9
|
-
include WebMock
|
10
12
|
|
11
13
|
def fixture(filename)
|
12
14
|
File.read(File.join(File.dirname(__FILE__), "fixtures", filename))
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: restfully
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 6
|
8
|
+
- 0
|
9
|
+
version: 0.6.0
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Cyril Rohr
|
@@ -9,69 +14,84 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date:
|
17
|
+
date: 2011-01-18 00:00:00 +01:00
|
13
18
|
default_executable: restfully
|
14
19
|
dependencies:
|
15
20
|
- !ruby/object:Gem::Dependency
|
16
21
|
name: rest-client
|
17
|
-
|
18
|
-
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
24
|
requirements:
|
21
25
|
- - ">="
|
22
26
|
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 4
|
23
30
|
version: "1.4"
|
24
|
-
|
31
|
+
type: :runtime
|
32
|
+
version_requirements: *id001
|
25
33
|
- !ruby/object:Gem::Dependency
|
26
34
|
name: json
|
27
|
-
|
28
|
-
|
29
|
-
version_requirements: !ruby/object:Gem::Requirement
|
35
|
+
prerelease: false
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
37
|
requirements:
|
31
38
|
- - ">="
|
32
39
|
- !ruby/object:Gem::Version
|
40
|
+
segments:
|
41
|
+
- 1
|
42
|
+
- 2
|
43
|
+
- 0
|
33
44
|
version: 1.2.0
|
34
|
-
|
45
|
+
type: :runtime
|
46
|
+
version_requirements: *id002
|
35
47
|
- !ruby/object:Gem::Dependency
|
36
48
|
name: backports
|
37
|
-
|
38
|
-
|
39
|
-
version_requirements: !ruby/object:Gem::Requirement
|
49
|
+
prerelease: false
|
50
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
40
51
|
requirements:
|
41
52
|
- - ">="
|
42
53
|
- !ruby/object:Gem::Version
|
54
|
+
segments:
|
55
|
+
- 0
|
43
56
|
version: "0"
|
44
|
-
|
57
|
+
type: :runtime
|
58
|
+
version_requirements: *id003
|
45
59
|
- !ruby/object:Gem::Dependency
|
46
60
|
name: webmock
|
47
|
-
|
48
|
-
|
49
|
-
version_requirements: !ruby/object:Gem::Requirement
|
61
|
+
prerelease: false
|
62
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
50
63
|
requirements:
|
51
64
|
- - ">="
|
52
65
|
- !ruby/object:Gem::Version
|
66
|
+
segments:
|
67
|
+
- 0
|
53
68
|
version: "0"
|
54
|
-
|
69
|
+
type: :development
|
70
|
+
version_requirements: *id004
|
55
71
|
- !ruby/object:Gem::Dependency
|
56
72
|
name: rspec
|
57
|
-
|
58
|
-
|
59
|
-
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
prerelease: false
|
74
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
60
75
|
requirements:
|
61
76
|
- - ">="
|
62
77
|
- !ruby/object:Gem::Version
|
78
|
+
segments:
|
79
|
+
- 0
|
63
80
|
version: "0"
|
64
|
-
|
81
|
+
type: :development
|
82
|
+
version_requirements: *id005
|
65
83
|
- !ruby/object:Gem::Dependency
|
66
84
|
name: json
|
67
|
-
|
68
|
-
|
69
|
-
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
prerelease: false
|
86
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
70
87
|
requirements:
|
71
88
|
- - ">="
|
72
89
|
- !ruby/object:Gem::Version
|
90
|
+
segments:
|
91
|
+
- 0
|
73
92
|
version: "0"
|
74
|
-
|
93
|
+
type: :development
|
94
|
+
version_requirements: *id006
|
75
95
|
description: Experimental code for auto-generation of wrappers on top of RESTful APIs that follow HATEOAS principles and provide OPTIONS methods and/or Allow headers.
|
76
96
|
email: cyril.rohr@gmail.com
|
77
97
|
executables:
|
@@ -139,18 +159,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
139
159
|
requirements:
|
140
160
|
- - ">="
|
141
161
|
- !ruby/object:Gem::Version
|
162
|
+
segments:
|
163
|
+
- 0
|
142
164
|
version: "0"
|
143
|
-
version:
|
144
165
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
166
|
requirements:
|
146
167
|
- - ">="
|
147
168
|
- !ruby/object:Gem::Version
|
169
|
+
segments:
|
170
|
+
- 0
|
148
171
|
version: "0"
|
149
|
-
version:
|
150
172
|
requirements: []
|
151
173
|
|
152
174
|
rubyforge_project:
|
153
|
-
rubygems_version: 1.3.
|
175
|
+
rubygems_version: 1.3.6
|
154
176
|
signing_key:
|
155
177
|
specification_version: 3
|
156
178
|
summary: Experimental code for auto-generation of wrappers on top of RESTful APIs that follow some specific conventions.
|