hyperclient 0.8.5 → 0.8.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +3 -3
- data/.travis.yml +6 -7
- data/CHANGELOG.md +7 -0
- data/Gemfile +1 -0
- data/README.md +35 -13
- data/Rakefile +1 -1
- data/features/steps/default_config.rb +1 -1
- data/hyperclient.gemspec +1 -1
- data/lib/hyperclient/entry_point.rb +2 -0
- data/lib/hyperclient/link.rb +2 -1
- data/lib/hyperclient/resource.rb +28 -1
- data/lib/hyperclient/version.rb +1 -1
- data/test/hyperclient/link_test.rb +10 -0
- data/test/hyperclient/resource_test.rb +6 -0
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 54fef5d6ab73927e7ac10dbccf6c1be3b4b7e32a
|
4
|
+
data.tar.gz: 41bf760d61b6f09bcf6a4526df9dcb04c56f1430
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b669fbd6b1be2cf46568da0e9351524602dc86eb0120168be5c1cbbf9cc22a50ee2f94985f315890507923db4d15f5350770a02b986fc7337bd4d0cec5e3c8ee
|
7
|
+
data.tar.gz: f7184b27bc26289af1e05b7f957a2ec44ecdd11bea8546ab608e875ee1c5f5f8d1b2efb8c80d9bd6c005710c4e3dc19c34edb450b4f39845aa10084acd65327a
|
data/.rubocop_todo.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on
|
3
|
+
# on 2017-08-26 18:01:43 +0100 using RuboCop version 0.42.0.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
@@ -9,9 +9,9 @@
|
|
9
9
|
# Offense count: 1
|
10
10
|
# Configuration parameters: CountComments.
|
11
11
|
Metrics/ClassLength:
|
12
|
-
Max:
|
12
|
+
Max: 110
|
13
13
|
|
14
|
-
# Offense count:
|
14
|
+
# Offense count: 97
|
15
15
|
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes.
|
16
16
|
# URISchemes: http, https
|
17
17
|
Metrics/LineLength:
|
data/.travis.yml
CHANGED
@@ -4,17 +4,16 @@ sudo: false
|
|
4
4
|
|
5
5
|
matrix:
|
6
6
|
include:
|
7
|
-
- rvm: 2.
|
7
|
+
- rvm: 2.4.1
|
8
|
+
- rvm: 2.4.1
|
8
9
|
script:
|
9
10
|
- bundle exec danger
|
10
|
-
- rvm:
|
11
|
-
- rvm:
|
12
|
-
- rvm: 2.2.
|
13
|
-
- rvm: 2.4
|
11
|
+
- rvm: jruby-9.1.12.0
|
12
|
+
- rvm: jruby-head
|
13
|
+
- rvm: 2.2.7
|
14
|
+
- rvm: 2.3.4
|
14
15
|
- rvm: rbx-2
|
15
16
|
- rvm: ruby-head
|
16
|
-
- rvm: jruby-head
|
17
|
-
- rvm: jruby-9.1.7.0
|
18
17
|
allow_failures:
|
19
18
|
- rvm: ruby-head
|
20
19
|
- rvm: jruby-head
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
### 0.8.6 (August 27, 2017)
|
2
|
+
|
3
|
+
* [#122](https://github.com/codegram/hyperclient/pull/122): Improve error message when server returns invalid data - [@ivoanjo](https://github.com/ivoanjo).
|
4
|
+
* [#125](https://github.com/codegram/hyperclient/pull/125): Add table of contents to readme and add note asking users to add their projects to the wiki - [@ivoanjo](https://github.com/ivoanjo).
|
5
|
+
* [#127](https://github.com/codegram/hyperclient/pull/127): Minor fixes: Fix warnings, and pry-byebug to dev Gemfile and tweak rubocop execution - [@ivoanjo](https://github.com/ivoanjo).
|
6
|
+
* [#128](https://github.com/codegram/hyperclient/pull/128): Fix link delegation returning nil for field with value false - [@ivoanjo](https://github.com/ivoanjo).
|
7
|
+
|
1
8
|
### 0.8.5 (July 5, 2017)
|
2
9
|
|
3
10
|
* [#120](https://github.com/codegram/hyperclient/pull/120): Replace non-working homepage link in gemspec - [@ivoanjo](https://github.com/ivoanjo).
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -8,11 +8,29 @@
|
|
8
8
|
|
9
9
|
Hyperclient is a Hypermedia API client written in Ruby. It fully supports [JSON HAL](http://stateless.co/hal_specification.html).
|
10
10
|
|
11
|
-
|
11
|
+
* [Hyperclient](#hyperclient)
|
12
|
+
* [Usage](#usage)
|
13
|
+
* [API Client](#api-client)
|
14
|
+
* [Resources and Attributes](#resources-and-attributes)
|
15
|
+
* [Links and Embedded Resources](#links-and-embedded-resources)
|
16
|
+
* [Templated Links](#templated-links)
|
17
|
+
* [Curies](#curies)
|
18
|
+
* [Attributes](#attributes)
|
19
|
+
* [HTTP](#http)
|
20
|
+
* [Asynchronous requests](#asynchronous-requests)
|
21
|
+
* [Testing Using Hyperclient](#testing-using-hyperclient)
|
22
|
+
* [Reference](#reference)
|
23
|
+
* [Hyperclient Users](#hyperclient-users)
|
24
|
+
* [Contributing](#contributing)
|
25
|
+
* [License](#license)
|
26
|
+
|
27
|
+
<sub><sup>ToC created with [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)</sup></sub>
|
28
|
+
|
29
|
+
# Usage
|
12
30
|
|
13
31
|
The examples in this README use the [Splines Demo API](https://github.com/ruby-grape/grape-with-roar) running [here](https://grape-with-roar.herokuapp.com/api). If you're upgrading from a previous version, please make sure to read [UPGRADING](UPGRADING.md).
|
14
32
|
|
15
|
-
|
33
|
+
## API Client
|
16
34
|
|
17
35
|
Create an API client.
|
18
36
|
|
@@ -85,7 +103,7 @@ api = Hyperclient.new('https://grape-with-roar.herokuapp.com/api')
|
|
85
103
|
api.connection.use :http_cache
|
86
104
|
```
|
87
105
|
|
88
|
-
|
106
|
+
## Resources and Attributes
|
89
107
|
|
90
108
|
Hyperclient will fetch and discover the resources from your API.
|
91
109
|
|
@@ -104,7 +122,7 @@ api.splines.each do |spline|
|
|
104
122
|
end
|
105
123
|
```
|
106
124
|
|
107
|
-
|
125
|
+
## Links and Embedded Resources
|
108
126
|
|
109
127
|
The splines example above followed a link called "splines". While you can, you do not need to specify the HAL navigational structure, including links or embedded resources. Hyperclient will resolve these for you. If you prefer, you can explicitly navigate the link structure via `_links`. In the following example the "splines" link leads to a collection of embedded splines. Invoking `api.splines` is equivalent to `api._links.splines._embedded.splines`.
|
110
128
|
|
@@ -112,7 +130,7 @@ The splines example above followed a link called "splines". While you can, you d
|
|
112
130
|
api._links.splines
|
113
131
|
```
|
114
132
|
|
115
|
-
|
133
|
+
## Templated Links
|
116
134
|
|
117
135
|
Templated links require variables to be expanded. For example, the demo API has a link called "spline" that requires a spline "uuid".
|
118
136
|
|
@@ -125,7 +143,7 @@ Invoking `api.spline(uuid: 'uuid').reticulated` is equivalent to `api._links.spl
|
|
125
143
|
|
126
144
|
The client is responsible for supplying all the necessary parameters. Templated links don't do any strict parameter name checking and don't support required vs. optional parameters. Parameters not declared by the API will be dropped and will not have any effect when passed to `_expand`.
|
127
145
|
|
128
|
-
|
146
|
+
## Curies
|
129
147
|
|
130
148
|
Curies are a suggested means by which to link documentation of a given resource. For example, the demo API contains very long links to images that use an "images" curie.
|
131
149
|
|
@@ -134,7 +152,7 @@ puts spline['image:thumbnail'] # => https://grape-with-roar.herokuapp.com/api/sp
|
|
134
152
|
puts spline.links._curies['image'].expand('thumbnail') # => /docs/images/thumbnail
|
135
153
|
```
|
136
154
|
|
137
|
-
|
155
|
+
## Attributes
|
138
156
|
|
139
157
|
Resource attributes can also be accessed as a hash.
|
140
158
|
|
@@ -144,7 +162,7 @@ puts spline.to_h # => {"uuid" => "uuid", "reticulated" => true}
|
|
144
162
|
|
145
163
|
The above is equivalent to `spline._attributes.to_h`.
|
146
164
|
|
147
|
-
|
165
|
+
## HTTP
|
148
166
|
|
149
167
|
Hyperclient uses [Faraday](http://github.com/lostisland/faraday) under the hood to perform HTTP calls. You can call any valid HTTP method on any resource.
|
150
168
|
|
@@ -187,7 +205,7 @@ spline._delete
|
|
187
205
|
|
188
206
|
HTTP methods always return a new instance of Resource.
|
189
207
|
|
190
|
-
|
208
|
+
## Asynchronous requests
|
191
209
|
|
192
210
|
By default, Hyperclient requests are performed asynchronously in a background thread pool via the [Futuroscope](https://github.com/codegram/futuroscope) gem. You can control the size of this pool by setting the `min_workers` and `max_workers` settings:
|
193
211
|
|
@@ -204,7 +222,7 @@ api = Hyperclient.new('https://grape-with-roar.herokuapp.com/api') do |client|
|
|
204
222
|
end
|
205
223
|
```
|
206
224
|
|
207
|
-
|
225
|
+
# Testing Using Hyperclient
|
208
226
|
|
209
227
|
You can combine RSpec, Faraday::Adapter::Rack and Hyperclient to test your HAL API without having to ever examine the raw JSON response.
|
210
228
|
|
@@ -233,14 +251,18 @@ end
|
|
233
251
|
|
234
252
|
For a complete example refer to [this Splines Demo API test](https://github.com/ruby-grape/grape-with-roar/blob/master/spec/api/splines_endpoint_with_hyperclient_spec.rb).
|
235
253
|
|
236
|
-
|
254
|
+
# Reference
|
237
255
|
|
238
256
|
[Hyperclient API Reference](http://rubydoc.org/github/codegram/hyperclient/master/frames).
|
239
257
|
|
240
|
-
|
258
|
+
# Hyperclient Users
|
259
|
+
|
260
|
+
Using Hyperclient? Add your project to our wiki, please: <https://github.com/codegram/hyperclient/wiki>.
|
261
|
+
|
262
|
+
# Contributing
|
241
263
|
|
242
264
|
Hyperclient is work of [many people](https://github.com/codegram/hyperclient/graphs/contributors). You're encouraged to submit [pull requests](https://github.com/codegram/hyperclient/pulls), [propose features and discuss issues](https://github.com/codegram/hyperclient/issues). See [CONTRIBUTING](CONTRIBUTING.md) for details.
|
243
265
|
|
244
|
-
|
266
|
+
# License
|
245
267
|
|
246
268
|
MIT License, see [LICENSE](LICENSE) for details. Copyright 2012-2014 [Codegram Technologies](http://codegram.com).
|
data/Rakefile
CHANGED
@@ -12,7 +12,7 @@ class Spinach::Features::DefaultConfig < Spinach::FeatureSteps
|
|
12
12
|
end
|
13
13
|
|
14
14
|
step 'I send some data to the API' do
|
15
|
-
stub_request(:post, 'http://api.example.org/posts')
|
15
|
+
stub_request(:post, 'http://api.example.org/posts').to_return(headers: { 'Content-Type' => 'application/hal+json' })
|
16
16
|
assert_equal 200, api._links.posts._post(title: 'My first blog post')._response.status
|
17
17
|
end
|
18
18
|
|
data/hyperclient.gemspec
CHANGED
@@ -4,7 +4,7 @@ require File.expand_path('../lib/hyperclient/version', __FILE__)
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
5
|
gem.authors = ['Oriol Gual']
|
6
6
|
gem.email = ['oriol.gual@gmail.com']
|
7
|
-
gem.description = '
|
7
|
+
gem.description = 'Hyperclient is a Ruby Hypermedia API client.'
|
8
8
|
gem.summary = ''
|
9
9
|
gem.homepage = 'https://github.com/codegram/hyperclient/'
|
10
10
|
gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
data/lib/hyperclient/link.rb
CHANGED
@@ -126,7 +126,8 @@ module Hyperclient
|
|
126
126
|
# Internal: Delegate the method further down the API if the resource cannot serve it.
|
127
127
|
def method_missing(method, *args, &block)
|
128
128
|
if _resource.respond_to?(method.to_s)
|
129
|
-
_resource.send(method, *args, &block)
|
129
|
+
result = _resource.send(method, *args, &block)
|
130
|
+
result.nil? ? delegate_method(method, *args, &block) : result
|
130
131
|
else
|
131
132
|
super
|
132
133
|
end
|
data/lib/hyperclient/resource.rb
CHANGED
@@ -1,6 +1,17 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
|
3
3
|
module Hyperclient
|
4
|
+
# Public: Exception that is raised when passing in invalid representation data
|
5
|
+
# for the resource.
|
6
|
+
class InvalidRepresentationError < ArgumentError
|
7
|
+
attr_reader :representation
|
8
|
+
|
9
|
+
def initialize(error_description, representation)
|
10
|
+
super(error_description)
|
11
|
+
@representation = representation
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
4
15
|
# Public: Represents a resource from your API. Its responsability is to
|
5
16
|
# ease the way you access its attributes, links and embedded resources.
|
6
17
|
class Resource
|
@@ -29,8 +40,9 @@ module Hyperclient
|
|
29
40
|
# representation - The hash with the HAL representation of the Resource.
|
30
41
|
# entry_point - The EntryPoint object to inject the configutation.
|
31
42
|
def initialize(representation, entry_point, response = nil)
|
32
|
-
representation = representation
|
43
|
+
representation = validate(representation)
|
33
44
|
links = representation['_links'] || {}
|
45
|
+
|
34
46
|
@_links = LinkCollection.new(links, links['curies'], entry_point)
|
35
47
|
@_embedded = ResourceCollection.new(representation['_embedded'], entry_point)
|
36
48
|
@_attributes = Attributes.new(representation)
|
@@ -68,6 +80,21 @@ module Hyperclient
|
|
68
80
|
|
69
81
|
private
|
70
82
|
|
83
|
+
# Internal: Ensures the received representation is a valid Hash-lookalike.
|
84
|
+
def validate(representation)
|
85
|
+
return {} unless representation
|
86
|
+
|
87
|
+
if representation.respond_to?(:to_hash)
|
88
|
+
representation.to_hash.dup
|
89
|
+
else
|
90
|
+
raise InvalidRepresentationError.new(
|
91
|
+
"Invalid representation for resource (got #{representation.class}, expected Hash). " \
|
92
|
+
"Is your web server returning JSON HAL data with a 'Content-Type: application/hal+json' header?",
|
93
|
+
representation
|
94
|
+
)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
71
98
|
# Internal: Returns the self Link of the Resource. Used to handle the HTTP
|
72
99
|
# methods.
|
73
100
|
def _self_link
|
data/lib/hyperclient/version.rb
CHANGED
@@ -479,6 +479,16 @@ module Hyperclient
|
|
479
479
|
resource.orders.first.id.must_equal 1
|
480
480
|
end
|
481
481
|
|
482
|
+
it 'can handle false values in the response' do
|
483
|
+
resource = Resource.new({ '_links' => { 'orders' => { 'href' => '/orders' } } }, entry_point)
|
484
|
+
|
485
|
+
stub_request(entry_point.connection) do |stub|
|
486
|
+
stub.get('http://api.example.org/orders') { [200, {}, { 'any' => false }] }
|
487
|
+
end
|
488
|
+
|
489
|
+
resource.orders.any.must_equal false
|
490
|
+
end
|
491
|
+
|
482
492
|
it "doesn't delegate when link key doesn't match" do
|
483
493
|
resource = Resource.new({ '_links' => { 'foos' => { 'href' => '/orders' } } }, entry_point)
|
484
494
|
|
@@ -40,6 +40,12 @@ module Hyperclient
|
|
40
40
|
|
41
41
|
resource._response.body.must_equal body
|
42
42
|
end
|
43
|
+
|
44
|
+
describe 'with an invalid representation' do
|
45
|
+
it 'raises an InvalidRepresentationError' do
|
46
|
+
proc { Resource.new('invalid representation data', entry_point) }.must_raise InvalidRepresentationError
|
47
|
+
end
|
48
|
+
end
|
43
49
|
end
|
44
50
|
|
45
51
|
describe '_links' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hyperclient
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oriol Gual
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-08-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -108,7 +108,7 @@ dependencies:
|
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
|
-
description:
|
111
|
+
description: Hyperclient is a Ruby Hypermedia API client.
|
112
112
|
email:
|
113
113
|
- oriol.gual@gmail.com
|
114
114
|
executables: []
|
@@ -183,7 +183,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
183
183
|
version: '0'
|
184
184
|
requirements: []
|
185
185
|
rubyforge_project:
|
186
|
-
rubygems_version: 2.6.
|
186
|
+
rubygems_version: 2.6.12
|
187
187
|
signing_key:
|
188
188
|
specification_version: 4
|
189
189
|
summary: ''
|