hyperclient 0.3.1 → 0.3.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.
- checksums.yaml +4 -4
- data/Gemfile.lock +4 -4
- data/Readme.md +35 -22
- data/lib/hyperclient/attributes.rb +3 -1
- data/lib/hyperclient/collection.rb +19 -1
- data/lib/hyperclient/link.rb +63 -5
- data/lib/hyperclient/link_collection.rb +1 -0
- data/lib/hyperclient/resource.rb +16 -1
- data/lib/hyperclient/version.rb +1 -1
- data/test/fixtures/element.json +4 -2
- data/test/hyperclient/attributes_test.rb +14 -0
- data/test/hyperclient/collection_test.rb +32 -1
- data/test/hyperclient/link_collection_test.rb +7 -0
- data/test/hyperclient/link_test.rb +71 -9
- data/test/hyperclient/resource_test.rb +70 -0
- metadata +29 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2f8dcf578c3841e548076c5a1433d0fa7eb47f1
|
4
|
+
data.tar.gz: b347af17c5a9d7d00ac5a5e92605eb95b4c35842
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d3f7074ba0269e8145fc748952afdb8f4749bb5ae8b1fca2ffe9382c7505056feba1aec934a0dccd297d6743bbddb726c3fa4afa381d640a0374be81aece1187
|
7
|
+
data.tar.gz: 70db877e65d8807d6d6872e48d43034f0e5ca3cce60fc1859688ad214f4e39e2cddd89e3ce8270a565eb40b82642f969475f3874991015c95c4ff621db9107e0
|
data/Gemfile.lock
CHANGED
@@ -9,7 +9,7 @@ GIT
|
|
9
9
|
PATH
|
10
10
|
remote: .
|
11
11
|
specs:
|
12
|
-
hyperclient (0.3.
|
12
|
+
hyperclient (0.3.2)
|
13
13
|
faraday (~> 0.8)
|
14
14
|
faraday_middleware (~> 0.9)
|
15
15
|
net-http-digest_auth (~> 1.2)
|
@@ -23,8 +23,8 @@ GEM
|
|
23
23
|
coderay (1.0.6)
|
24
24
|
colorize (0.5.8)
|
25
25
|
crack (0.3.1)
|
26
|
-
faraday (0.8.
|
27
|
-
multipart-post (~> 1.
|
26
|
+
faraday (0.8.8)
|
27
|
+
multipart-post (~> 1.2.0)
|
28
28
|
faraday_middleware (0.9.0)
|
29
29
|
faraday (>= 0.7.4, < 0.9)
|
30
30
|
ffi (1.0.11)
|
@@ -44,7 +44,7 @@ GEM
|
|
44
44
|
mocha (0.13.1)
|
45
45
|
metaclass (~> 0.0.1)
|
46
46
|
multi_json (1.3.6)
|
47
|
-
multipart-post (1.
|
47
|
+
multipart-post (1.2.0)
|
48
48
|
net-http-digest_auth (1.2.1)
|
49
49
|
pry (0.9.9.6)
|
50
50
|
coderay (~> 1.0.5)
|
data/Readme.md
CHANGED
@@ -13,12 +13,12 @@ Hyperclient is a Ruby Hypermedia API client written in Ruby.
|
|
13
13
|
|
14
14
|
Example API client:
|
15
15
|
|
16
|
-
|
16
|
+
```ruby
|
17
17
|
api = Hyperclient.new('http://myapp.com/api').tap do |api|
|
18
18
|
api.digest_auth('user', 'password')
|
19
19
|
api.headers.merge({'accept-encoding' => 'deflate, gzip'})
|
20
20
|
end
|
21
|
-
|
21
|
+
```
|
22
22
|
|
23
23
|
By default, Hyperclient adds `application/json` as `Content-Type` and `Accept`
|
24
24
|
headers. It will also sent requests as JSON and parse JSON responses.
|
@@ -37,60 +37,73 @@ Hyperclient will try to fetch and discover the resources from your API.
|
|
37
37
|
|
38
38
|
Accessing the links for a given resource is quite straightforward:
|
39
39
|
|
40
|
-
|
40
|
+
```ruby
|
41
41
|
api.links.posts_categories
|
42
42
|
# => #<Resource ...>
|
43
|
-
|
43
|
+
```
|
44
44
|
|
45
45
|
You can also iterate between all the links:
|
46
46
|
|
47
|
-
|
47
|
+
```ruby
|
48
48
|
api.links.each do |name, link|
|
49
49
|
puts name, link.url
|
50
50
|
end
|
51
|
-
|
51
|
+
```
|
52
52
|
|
53
53
|
Actually, you can call any [Enumerable][enumerable] method :D
|
54
54
|
|
55
55
|
If a Resource doesn't have friendly name you can always access it as a Hash:
|
56
56
|
|
57
|
-
|
57
|
+
```ruby
|
58
58
|
api.links['http://myapi.org/rels/post_categories']
|
59
|
-
|
59
|
+
```
|
60
60
|
|
61
61
|
### Embedded resources
|
62
62
|
|
63
63
|
Accessing embedded resources is similar to accessing links:
|
64
64
|
|
65
|
-
|
65
|
+
```ruby
|
66
66
|
api.embedded.posts
|
67
|
-
|
67
|
+
```
|
68
68
|
|
69
69
|
And you can also iterate between them:
|
70
70
|
|
71
|
-
|
71
|
+
```ruby
|
72
72
|
api.embedded.each do |name, resource|
|
73
73
|
puts name, resource.attributes
|
74
74
|
end
|
75
|
-
|
75
|
+
```
|
76
76
|
|
77
77
|
You can even chain different calls (this also applies for links):
|
78
78
|
|
79
|
-
|
79
|
+
```ruby
|
80
80
|
api.embedded.posts.first.links.author
|
81
|
-
|
81
|
+
```
|
82
82
|
|
83
83
|
### Attributes
|
84
84
|
|
85
85
|
Not only you might have links and embedded resources in a Resource, but also
|
86
86
|
its attributes:
|
87
87
|
|
88
|
-
|
88
|
+
```ruby
|
89
89
|
api.embedded.posts.first.attributes
|
90
90
|
# => {title: 'Linting the hell out of your Ruby classes with Pelusa',
|
91
91
|
teaser: 'Gain new insights about your code thanks to static analysis',
|
92
92
|
body: '...' }
|
93
|
-
|
93
|
+
```
|
94
|
+
|
95
|
+
You can access the attribute values via attribute methods, or as a hash:
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
api.embedded.posts.first.attributes.title
|
99
|
+
# => 'Linting the hell out of your Ruby classes with Pelusa'
|
100
|
+
|
101
|
+
api.embedded.posts.first.attributes['title']
|
102
|
+
# => 'Linting the hell out of your Ruby classes with Pelusa'
|
103
|
+
|
104
|
+
api.embedded.posts.first.attributes.fetch('title')
|
105
|
+
# => 'Linting the hell out of your Ruby classes with Pelusa'
|
106
|
+
```
|
94
107
|
|
95
108
|
### HTTP
|
96
109
|
|
@@ -100,7 +113,7 @@ with it, right?
|
|
100
113
|
Hyperclient uses [Faraday][faraday] under the hood to perform HTTP calls. You can
|
101
114
|
call any valid HTTP method on any Resource:
|
102
115
|
|
103
|
-
|
116
|
+
```ruby
|
104
117
|
post = api.embedded.posts.first
|
105
118
|
post.get
|
106
119
|
post.head
|
@@ -111,22 +124,22 @@ post.options
|
|
111
124
|
|
112
125
|
posts = api.links.posts
|
113
126
|
posts.post({title: "I'm a blogger!", body: 'Wohoo!!'})
|
114
|
-
|
127
|
+
```
|
115
128
|
|
116
129
|
If you have a templated link you can expand it like so:
|
117
130
|
|
118
|
-
|
131
|
+
```ruby
|
119
132
|
api.links.post.expand(:id => 3).first
|
120
133
|
# => #<Resource ...>
|
121
|
-
|
134
|
+
```
|
122
135
|
|
123
136
|
You can access the Faraday connection (to add middlewares or do whatever
|
124
137
|
you want) by calling `connection` on the entry point. As an example, you could use the [faraday-http-cache-middleware](https://github.com/plataformatec/faraday-http-cache)
|
125
138
|
:
|
126
139
|
|
127
|
-
|
140
|
+
```ruby
|
128
141
|
api.connection.use :http_cache
|
129
|
-
|
142
|
+
```
|
130
143
|
|
131
144
|
## Other
|
132
145
|
|
@@ -9,13 +9,15 @@ module Hyperclient
|
|
9
9
|
# resource.attributes.title
|
10
10
|
#
|
11
11
|
class Attributes < Collection
|
12
|
+
RESERVED_PROPERTIES = [/^_links$/, /^_embedded$/] # http://tools.ietf.org/html/draft-kelly-json-hal#section-4.1
|
13
|
+
|
12
14
|
# Public: Initializes the Attributes of a Resource.
|
13
15
|
#
|
14
16
|
# representation - The hash with the HAL representation of the Resource.
|
15
17
|
#
|
16
18
|
def initialize(representation)
|
17
19
|
@collection = if representation.is_a?(Hash)
|
18
|
-
representation.delete_if {|key, value| key
|
20
|
+
representation.delete_if {|key, value| RESERVED_PROPERTIES.any? {|p| p.match(key) } }
|
19
21
|
else
|
20
22
|
representation
|
21
23
|
end
|
@@ -25,6 +25,23 @@ module Hyperclient
|
|
25
25
|
@collection.each(&block)
|
26
26
|
end
|
27
27
|
|
28
|
+
def include?(obj)
|
29
|
+
@collection.include?(obj)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Public: Returns a value from the collection for the given key.
|
33
|
+
# If the key can’t be found, there are several options:
|
34
|
+
# With no other arguments, it will raise an KeyError exception;
|
35
|
+
# if default is given, then that will be returned;
|
36
|
+
#
|
37
|
+
# key - A String or Symbol of the value to get from the collection.
|
38
|
+
# default - An optional value to be returned if the key is not found.
|
39
|
+
#
|
40
|
+
# Returns an Object.
|
41
|
+
def fetch(*args)
|
42
|
+
@collection.fetch(*args)
|
43
|
+
end
|
44
|
+
|
28
45
|
# Public: Provides Hash-like access to the collection.
|
29
46
|
#
|
30
47
|
# name - A String or Symbol of the value to get from the collection.
|
@@ -37,9 +54,10 @@ module Hyperclient
|
|
37
54
|
# Public: Returns the wrapped collection as a hash.
|
38
55
|
#
|
39
56
|
# Returns a Hash.
|
40
|
-
def
|
57
|
+
def to_h
|
41
58
|
@collection.to_hash
|
42
59
|
end
|
60
|
+
alias_method :to_hash, :to_h
|
43
61
|
|
44
62
|
def to_s
|
45
63
|
to_hash
|
data/lib/hyperclient/link.rb
CHANGED
@@ -42,12 +42,57 @@ module Hyperclient
|
|
42
42
|
return @link['href'] unless templated?
|
43
43
|
raise MissingURITemplateVariablesException if @uri_variables == nil
|
44
44
|
|
45
|
-
@url ||=
|
45
|
+
@url ||= uri_template.expand(@uri_variables)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Public: Returns an array of variables from the URITemplate.
|
49
|
+
#
|
50
|
+
# Returns an empty array for regular URIs.
|
51
|
+
def variables
|
52
|
+
uri_template.variables
|
53
|
+
end
|
54
|
+
|
55
|
+
# Public: Returns the type property of the Link
|
56
|
+
def type
|
57
|
+
@link['type']
|
58
|
+
end
|
59
|
+
|
60
|
+
# Public: Returns the name property of the Link
|
61
|
+
def name
|
62
|
+
@link['name']
|
63
|
+
end
|
64
|
+
|
65
|
+
# Public: Returns the deprecation property of the Link
|
66
|
+
def deprecation
|
67
|
+
@link['deprecation']
|
68
|
+
end
|
69
|
+
|
70
|
+
# Public: Returns the profile property of the Link
|
71
|
+
def profile
|
72
|
+
@link['profile']
|
73
|
+
end
|
74
|
+
|
75
|
+
# Public: Returns the title property of the Link
|
76
|
+
def title
|
77
|
+
@link['title']
|
78
|
+
end
|
79
|
+
|
80
|
+
# Public: Returns the hreflang property of the Link
|
81
|
+
def hreflang
|
82
|
+
@link['hreflang']
|
46
83
|
end
|
47
84
|
|
48
85
|
# Public: Returns the Resource which the Link is pointing to.
|
49
86
|
def resource
|
50
|
-
@resource ||=
|
87
|
+
@resource ||= begin
|
88
|
+
response = get
|
89
|
+
|
90
|
+
if response.success?
|
91
|
+
Resource.new(response.body, @entry_point, response)
|
92
|
+
else
|
93
|
+
Resource.new(nil, @entry_point, response)
|
94
|
+
end
|
95
|
+
end
|
51
96
|
end
|
52
97
|
|
53
98
|
def connection
|
@@ -70,15 +115,15 @@ module Hyperclient
|
|
70
115
|
connection.delete(url)
|
71
116
|
end
|
72
117
|
|
73
|
-
def post(params)
|
118
|
+
def post(params = {})
|
74
119
|
connection.post(url, params)
|
75
120
|
end
|
76
121
|
|
77
|
-
def put(params)
|
122
|
+
def put(params = {})
|
78
123
|
connection.put(url, params)
|
79
124
|
end
|
80
125
|
|
81
|
-
def patch(params)
|
126
|
+
def patch(params = {})
|
82
127
|
connection.patch(url, params)
|
83
128
|
end
|
84
129
|
|
@@ -104,6 +149,19 @@ module Hyperclient
|
|
104
149
|
def respond_to_missing?(method, include_private = false)
|
105
150
|
resource.respond_to?(method.to_s)
|
106
151
|
end
|
152
|
+
|
153
|
+
# Internal: avoid delegating to resource
|
154
|
+
#
|
155
|
+
# #to_ary is called for implicit array coersion (such as parallel assignment
|
156
|
+
# or Array#flatten). Returning nil tells Ruby that this record is not Array-like.
|
157
|
+
def to_ary
|
158
|
+
nil
|
159
|
+
end
|
160
|
+
|
161
|
+
# Internal: Memoization for a URITemplate instance
|
162
|
+
def uri_template
|
163
|
+
@uri_template ||= URITemplate.new(@link['href'])
|
164
|
+
end
|
107
165
|
end
|
108
166
|
|
109
167
|
# Public: Exception that is raised when building a templated Link without uri
|
@@ -30,6 +30,7 @@ module Hyperclient
|
|
30
30
|
#
|
31
31
|
# Returns a Link or an array of Links when given an Array.
|
32
32
|
def build_link(link_or_links, entry_point)
|
33
|
+
return unless link_or_links
|
33
34
|
return Link.new(link_or_links, entry_point) unless link_or_links.respond_to?(:to_ary)
|
34
35
|
|
35
36
|
link_or_links.collect do |link|
|
data/lib/hyperclient/resource.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'forwardable'
|
1
2
|
require 'hyperclient/attributes'
|
2
3
|
require 'hyperclient/link_collection'
|
3
4
|
require 'hyperclient/resource_collection'
|
@@ -18,6 +19,10 @@ module Hyperclient
|
|
18
19
|
# ResourceCollection.
|
19
20
|
attr_reader :embedded
|
20
21
|
|
22
|
+
# Public: Returns the response object for the HTTP request that created this
|
23
|
+
# resource, if one exists.
|
24
|
+
attr_reader :response
|
25
|
+
|
21
26
|
# Public: Delegate all HTTP methods (get, post, put, delete, options and
|
22
27
|
# head) to its self link.
|
23
28
|
def_delegators :self_link, :get, :post, :put, :delete, :options, :head
|
@@ -26,17 +31,27 @@ module Hyperclient
|
|
26
31
|
#
|
27
32
|
# representation - The hash with the HAL representation of the Resource.
|
28
33
|
# entry_point - The EntryPoint object to inject the configutation.
|
29
|
-
def initialize(representation, entry_point)
|
34
|
+
def initialize(representation, entry_point, response=nil)
|
35
|
+
representation = representation ? representation.dup : {}
|
30
36
|
@links = LinkCollection.new(representation['_links'], entry_point)
|
31
37
|
@embedded = ResourceCollection.new(representation['_embedded'], entry_point)
|
32
38
|
@attributes = Attributes.new(representation)
|
33
39
|
@entry_point = entry_point
|
40
|
+
@response = response
|
34
41
|
end
|
35
42
|
|
36
43
|
def inspect
|
37
44
|
"#<#{self.class.name} self_link:#{self_link.inspect} attributes:#{@attributes.inspect}>"
|
38
45
|
end
|
39
46
|
|
47
|
+
def success?
|
48
|
+
response && response.success?
|
49
|
+
end
|
50
|
+
|
51
|
+
def status
|
52
|
+
response && response.status
|
53
|
+
end
|
54
|
+
|
40
55
|
private
|
41
56
|
# Internal: Returns the self Link of the Resource. Used to handle the HTTP
|
42
57
|
# methods.
|
data/lib/hyperclient/version.rb
CHANGED
data/test/fixtures/element.json
CHANGED
@@ -14,11 +14,13 @@
|
|
14
14
|
{
|
15
15
|
"href": "/gizmos/2"
|
16
16
|
}
|
17
|
-
]
|
17
|
+
],
|
18
|
+
"null_link": null
|
18
19
|
},
|
19
20
|
"title": "Real World ASP.NET MVC3",
|
20
21
|
"description": "In this advanced, somewhat-opinionated production you'll get your very own startup off the ground using ASP.NET MVC 3...",
|
21
22
|
"permitted": true,
|
23
|
+
"_hidden_attribute": "useful value",
|
22
24
|
"_embedded": {
|
23
25
|
"author": {
|
24
26
|
"_links": {
|
@@ -59,4 +61,4 @@
|
|
59
61
|
}
|
60
62
|
]
|
61
63
|
}
|
62
|
-
}
|
64
|
+
}
|
@@ -19,6 +19,20 @@ module Hyperclient
|
|
19
19
|
attributes.wont_respond_to :_embedded
|
20
20
|
end
|
21
21
|
|
22
|
+
it 'sets normal attributes' do
|
23
|
+
attributes.must_respond_to :permitted
|
24
|
+
attributes.permitted.must_equal true
|
25
|
+
|
26
|
+
attributes.must_respond_to :title
|
27
|
+
attributes.title.must_equal "Real World ASP.NET MVC3"
|
28
|
+
end
|
29
|
+
|
30
|
+
# Underscores should be allowed per http://tools.ietf.org/html/draft-kelly-json-hal#appendix-B.4
|
31
|
+
it 'sets _hidden_attribute as an attribute' do
|
32
|
+
attributes.must_respond_to :_hidden_attribute
|
33
|
+
attributes._hidden_attribute.must_equal 'useful value'
|
34
|
+
end
|
35
|
+
|
22
36
|
it 'is a collection' do
|
23
37
|
Attributes.ancestors.must_include Collection
|
24
38
|
end
|
@@ -32,7 +32,7 @@ module Hyperclient
|
|
32
32
|
name
|
33
33
|
end
|
34
34
|
|
35
|
-
names.must_equal ['_links', 'title', 'description', 'permitted', '_embedded']
|
35
|
+
names.must_equal ['_links', 'title', 'description', 'permitted', '_hidden_attribute', '_embedded']
|
36
36
|
end
|
37
37
|
|
38
38
|
describe '#to_hash' do
|
@@ -40,6 +40,37 @@ module Hyperclient
|
|
40
40
|
collection.to_hash.must_be_kind_of Hash
|
41
41
|
end
|
42
42
|
end
|
43
|
+
|
44
|
+
describe 'include?' do
|
45
|
+
it 'returns true for keys that exist' do
|
46
|
+
collection.include?('_links').must_equal true
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'returns false for missing keys' do
|
50
|
+
collection.include?('missing key').must_equal false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#fetch' do
|
55
|
+
it 'returns the value for keys that exist' do
|
56
|
+
collection.fetch('title').must_equal "Real World ASP.NET MVC3"
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'raises an error for missing keys' do
|
60
|
+
Proc.new { collection.fetch('missing key') }.must_raise KeyError
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'with a default value' do
|
64
|
+
it 'returns the value for keys that exist' do
|
65
|
+
collection.fetch('title', 'default').must_equal "Real World ASP.NET MVC3"
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'returns the default value for missing keys' do
|
69
|
+
collection.fetch('missing key', 'default').must_equal 'default'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
43
74
|
end
|
44
75
|
end
|
45
76
|
|
@@ -8,6 +8,20 @@ module Hyperclient
|
|
8
8
|
EntryPoint.new('http://api.example.org/')
|
9
9
|
end
|
10
10
|
|
11
|
+
%w(type deprecation name profile title hreflang).each do |prop|
|
12
|
+
describe prop do
|
13
|
+
it "returns the property value" do
|
14
|
+
link = Link.new({prop => 'value'}, entry_point)
|
15
|
+
link.send(prop).must_equal 'value'
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'returns nil if the property is not present' do
|
19
|
+
link = Link.new({}, entry_point)
|
20
|
+
link.send(prop).must_equal nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
11
25
|
describe 'templated?' do
|
12
26
|
it 'returns true if the link is templated' do
|
13
27
|
link = Link.new({'templated' => true}, entry_point)
|
@@ -22,6 +36,20 @@ module Hyperclient
|
|
22
36
|
end
|
23
37
|
end
|
24
38
|
|
39
|
+
describe 'variables' do
|
40
|
+
it 'returns a list of required variables' do
|
41
|
+
link = Link.new({'href' => '/orders{?id,owner}', 'templated' => true}, entry_point)
|
42
|
+
|
43
|
+
link.variables.must_equal ['id', 'owner']
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'returns an empty array for untemplated links' do
|
47
|
+
link = Link.new({'href' => '/orders'}, entry_point)
|
48
|
+
|
49
|
+
link.variables.must_equal []
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
25
53
|
describe 'expand' do
|
26
54
|
it 'buils a Link with the templated URI representation' do
|
27
55
|
link = Link.new({'href' => '/orders{?id}', 'templated' => true}, entry_point)
|
@@ -58,10 +86,23 @@ module Hyperclient
|
|
58
86
|
|
59
87
|
describe 'resource' do
|
60
88
|
it 'builds a resource with the link href representation' do
|
61
|
-
|
89
|
+
mock_response = mock(body: {}, success?: true)
|
90
|
+
|
91
|
+
Resource.expects(:new).with({}, entry_point, mock_response)
|
92
|
+
|
93
|
+
link = Link.new({'href' => '/'}, entry_point)
|
94
|
+
link.expects(:get).returns(mock_response)
|
95
|
+
|
96
|
+
link.resource
|
97
|
+
end
|
98
|
+
|
99
|
+
it "has an empty body when the response fails" do
|
100
|
+
mock_response = mock(success?: false)
|
101
|
+
|
102
|
+
Resource.expects(:new).with(nil, entry_point, mock_response)
|
62
103
|
|
63
104
|
link = Link.new({'href' => '/'}, entry_point)
|
64
|
-
link.expects(:get).returns(
|
105
|
+
link.expects(:get).returns(mock_response)
|
65
106
|
|
66
107
|
link.resource
|
67
108
|
end
|
@@ -110,30 +151,45 @@ module Hyperclient
|
|
110
151
|
end
|
111
152
|
|
112
153
|
describe 'post' do
|
113
|
-
|
114
|
-
link = Link.new({'href' => '/productions/1'}, entry_point)
|
154
|
+
let(:link) { Link.new({'href' => '/productions/1'}, entry_point) }
|
115
155
|
|
156
|
+
it 'sends a POST request with the link url and params' do
|
116
157
|
entry_point.connection.expects(:post).with('/productions/1', {'foo' => 'bar'})
|
117
158
|
link.post({'foo' => 'bar'})
|
118
159
|
end
|
160
|
+
|
161
|
+
it 'defaults params to an empty hash' do
|
162
|
+
entry_point.connection.expects(:post).with('/productions/1', {})
|
163
|
+
link.post
|
164
|
+
end
|
119
165
|
end
|
120
166
|
|
121
167
|
describe 'put' do
|
122
|
-
|
123
|
-
link = Link.new({'href' => '/productions/1'}, entry_point)
|
168
|
+
let(:link) { Link.new({'href' => '/productions/1'}, entry_point) }
|
124
169
|
|
170
|
+
it 'sends a PUT request with the link url and params' do
|
125
171
|
entry_point.connection.expects(:put).with('/productions/1', {'foo' => 'bar'})
|
126
172
|
link.put({'foo' => 'bar'})
|
127
173
|
end
|
174
|
+
|
175
|
+
it 'defaults params to an empty hash' do
|
176
|
+
entry_point.connection.expects(:put).with('/productions/1', {})
|
177
|
+
link.put
|
178
|
+
end
|
128
179
|
end
|
129
180
|
|
130
181
|
describe 'patch' do
|
131
|
-
|
132
|
-
link = Link.new({'href' => '/productions/1'}, entry_point)
|
182
|
+
let(:link) { Link.new({'href' => '/productions/1'}, entry_point) }
|
133
183
|
|
184
|
+
it 'sends a PATCH request with the link url and params' do
|
134
185
|
entry_point.connection.expects(:patch).with('/productions/1', {'foo' => 'bar'})
|
135
186
|
link.patch({'foo' => 'bar'})
|
136
187
|
end
|
188
|
+
|
189
|
+
it 'defaults params to an empty hash' do
|
190
|
+
entry_point.connection.expects(:patch).with('/productions/1', {})
|
191
|
+
link.patch
|
192
|
+
end
|
137
193
|
end
|
138
194
|
|
139
195
|
describe 'inspect' do
|
@@ -149,13 +205,14 @@ module Hyperclient
|
|
149
205
|
before do
|
150
206
|
stub_request(:get, "http://myapi.org/orders").
|
151
207
|
to_return(body: '{"resource": "This is the resource"}')
|
152
|
-
Resource.
|
208
|
+
Resource.stubs(:new).returns(resource)
|
153
209
|
end
|
154
210
|
|
155
211
|
let(:link) { Link.new({'href' => 'http://myapi.org/orders'}, entry_point) }
|
156
212
|
let(:resource) { mock('Resource') }
|
157
213
|
|
158
214
|
it 'delegates unkown methods to the resource' do
|
215
|
+
Resource.expects(:new).returns(resource).at_least_once
|
159
216
|
resource.expects(:embedded)
|
160
217
|
|
161
218
|
link.embedded
|
@@ -169,6 +226,11 @@ module Hyperclient
|
|
169
226
|
resource.expects(:respond_to?).with('embedded').returns(true)
|
170
227
|
link.respond_to?(:embedded).must_equal true
|
171
228
|
end
|
229
|
+
|
230
|
+
it 'does not delegate to_ary to resource' do
|
231
|
+
resource.expects(:to_ary).never
|
232
|
+
[[link, link]].flatten.must_equal [link, link]
|
233
|
+
end
|
172
234
|
end
|
173
235
|
end
|
174
236
|
end
|
@@ -23,6 +23,24 @@ module Hyperclient
|
|
23
23
|
|
24
24
|
Resource.new({'_embedded' => {"orders" => [] }}, entry_point)
|
25
25
|
end
|
26
|
+
|
27
|
+
it "initializes the response" do
|
28
|
+
mock_response = mock(body: {})
|
29
|
+
|
30
|
+
resource = Resource.new(mock_response.body, entry_point, mock_response)
|
31
|
+
|
32
|
+
resource.response.must_equal mock_response
|
33
|
+
end
|
34
|
+
|
35
|
+
it "does not mutate the response.body" do
|
36
|
+
body = { 'foo' => 'bar', '_links' => {}, '_embedded' => {} }
|
37
|
+
mock_response = stub(body: body.dup)
|
38
|
+
|
39
|
+
resource = Resource.new(mock_response.body, entry_point, mock_response)
|
40
|
+
|
41
|
+
resource.response.body.must_equal body
|
42
|
+
end
|
43
|
+
|
26
44
|
end
|
27
45
|
|
28
46
|
describe 'accessors' do
|
@@ -58,5 +76,57 @@ module Hyperclient
|
|
58
76
|
|
59
77
|
resource.get
|
60
78
|
end
|
79
|
+
|
80
|
+
describe ".success?" do
|
81
|
+
describe "with a response object" do
|
82
|
+
let(:resource) do
|
83
|
+
Resource.new({}, entry_point, mock_response)
|
84
|
+
end
|
85
|
+
|
86
|
+
let(:mock_response) do
|
87
|
+
mock(success?: true)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "proxies to the response object" do
|
91
|
+
resource.success?.must_equal true
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "without a response object" do
|
96
|
+
let(:resource) do
|
97
|
+
Resource.new({}, entry_point)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "returns nil" do
|
101
|
+
resource.success?.must_be_nil
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe ".status" do
|
107
|
+
describe "with a response object" do
|
108
|
+
let(:resource) do
|
109
|
+
Resource.new({}, entry_point, mock_response)
|
110
|
+
end
|
111
|
+
|
112
|
+
let(:mock_response) do
|
113
|
+
mock(status: 200)
|
114
|
+
end
|
115
|
+
|
116
|
+
it "proxies to the response object" do
|
117
|
+
resource.status.must_equal 200
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe "without a response object" do
|
122
|
+
let(:resource) do
|
123
|
+
Resource.new({}, entry_point)
|
124
|
+
end
|
125
|
+
|
126
|
+
it "returns nil" do
|
127
|
+
resource.status.must_be_nil
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
61
131
|
end
|
62
132
|
end
|
metadata
CHANGED
@@ -1,153 +1,153 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hyperclient
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oriol Gual
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-12-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0.8'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0.8'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: faraday_middleware
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0.9'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0.9'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: uri_template
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - ~>
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0.5'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - ~>
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0.5'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: net-http-digest_auth
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - ~>
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '1.2'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - ~>
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '1.2'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: minitest
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - ~>
|
73
|
+
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: 3.4.0
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - ~>
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 3.4.0
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: turn
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - ~>
|
87
|
+
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0.9'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - ~>
|
94
|
+
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0.9'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: webmock
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- - ~>
|
101
|
+
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '1.8'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- - ~>
|
108
|
+
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '1.8'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: mocha
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
|
-
- - ~>
|
115
|
+
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
117
|
version: '0.13'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
|
-
- - ~>
|
122
|
+
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0.13'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: rack-test
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
|
-
- - ~>
|
129
|
+
- - "~>"
|
130
130
|
- !ruby/object:Gem::Version
|
131
131
|
version: '0.6'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
|
-
- - ~>
|
136
|
+
- - "~>"
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0.6'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
140
|
name: spinach
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
|
-
- -
|
143
|
+
- - ">="
|
144
144
|
- !ruby/object:Gem::Version
|
145
145
|
version: '0'
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
|
-
- -
|
150
|
+
- - ">="
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '0'
|
153
153
|
description: HyperClient is a Ruby Hypermedia API client.
|
@@ -157,10 +157,10 @@ executables: []
|
|
157
157
|
extensions: []
|
158
158
|
extra_rdoc_files: []
|
159
159
|
files:
|
160
|
-
- .gitignore
|
161
|
-
- .rvmrc
|
162
|
-
- .travis.yml
|
163
|
-
- .yardopts
|
160
|
+
- ".gitignore"
|
161
|
+
- ".rvmrc"
|
162
|
+
- ".travis.yml"
|
163
|
+
- ".yardopts"
|
164
164
|
- CHANGELOG.md
|
165
165
|
- Gemfile
|
166
166
|
- Gemfile.lock
|
@@ -213,17 +213,17 @@ require_paths:
|
|
213
213
|
- lib
|
214
214
|
required_ruby_version: !ruby/object:Gem::Requirement
|
215
215
|
requirements:
|
216
|
-
- -
|
216
|
+
- - ">="
|
217
217
|
- !ruby/object:Gem::Version
|
218
218
|
version: '0'
|
219
219
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
220
220
|
requirements:
|
221
|
-
- -
|
221
|
+
- - ">="
|
222
222
|
- !ruby/object:Gem::Version
|
223
223
|
version: '0'
|
224
224
|
requirements: []
|
225
225
|
rubyforge_project:
|
226
|
-
rubygems_version: 2.
|
226
|
+
rubygems_version: 2.2.0
|
227
227
|
signing_key:
|
228
228
|
specification_version: 4
|
229
229
|
summary: ''
|