excon-hypermedia 0.4.3 → 0.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 912319706191a6c2866f3c5e8a7f9d6c16631149
4
- data.tar.gz: 5309fb839091943003bb4dfe9be37c908fc0410d
3
+ metadata.gz: 6bc648cfd5761dfb1236aada3be47b061620a3ad
4
+ data.tar.gz: f0fc534b110a5de92cbe548a4dbe5eb4bcb6f5e6
5
5
  SHA512:
6
- metadata.gz: 0d196a5a238fba1fcfae2ed1cf3287c2f5b42f1ee9bd837c5e4b93c13407a511b2566cc1bcec76524752121ef464427737cdad05c69d2dbdc76292e36fb924b5
7
- data.tar.gz: b6f03792762adcc3e2d41af35bbdb8f6a2c21afbe3c09f72df20f7cc8ae29285777a726f0cca10dbdf373f73ebdcaf3824c342ad57f4489fe232d2c5f5289fa7
6
+ metadata.gz: 83c3ec47d43ce609a789f2bf0ae0281822ae0b4ba25b00596516ef7ed54e9ecc8ab4f3e834e642172b4a1560da4c8184aa4f6a6ac611f63dc84f22e19b4ee226
7
+ data.tar.gz: 74fb5d0362acce99b511533c487d18612c81f0c8b455d62633c6fd52e74eb8a262429e6873913e5a5f60e5efae9fdda15132c1602b38a3597e02e0573bf929ea
data/.wercker.yml CHANGED
@@ -1,5 +1,29 @@
1
- box: ruby:2.3
2
- build:
1
+ ruby-latest:
2
+ box: ruby:latest
3
+ steps:
4
+ - bundle-install
5
+ - script:
6
+ name: tests
7
+ code: bundle exec rake
8
+
9
+ ruby-23:
10
+ box: ruby:2.3
11
+ steps:
12
+ - bundle-install
13
+ - script:
14
+ name: tests
15
+ code: bundle exec rake
16
+
17
+ ruby-22:
18
+ box: ruby:2.2
19
+ steps:
20
+ - bundle-install
21
+ - script:
22
+ name: tests
23
+ code: bundle exec rake
24
+
25
+ ruby-21:
26
+ box: ruby:2.1
3
27
  steps:
4
28
  - bundle-install
5
29
  - script:
data/README.md CHANGED
@@ -10,6 +10,8 @@ Teaches [Excon][] how to talk to [HyperMedia APIs][hypermedia].
10
10
  * [relations](#relations)
11
11
  * [properties](#properties)
12
12
  * [embedded](#embedded)
13
+ * [Hypertext Cache Pattern](#hypertext-cache-pattern)
14
+ * [shortcuts](#shortcuts)
13
15
  * [License](#license)
14
16
 
15
17
  ## Installation
@@ -254,8 +256,51 @@ For more information on this concept, see the [formal specification][_embedded].
254
256
  Embedded resources work the same as the top-level resource:
255
257
 
256
258
  ```ruby
257
- product._embedded.pump.class # => Excon::HyperMedia::ResourceObject
258
- product._embedded.pump.weight # => '2kg'
259
+ product.resource._embedded.pump.class # => Excon::HyperMedia::ResourceObject
260
+ product.resource._embedded.pump.weight # => '2kg'
261
+ ```
262
+
263
+ ### Hypertext Cache Pattern
264
+
265
+ You can leverage embedded resources to dynamically reduce the number of requests
266
+ you have to make to get the desired results, improving the efficiency and
267
+ performance of the application. This technique is called
268
+ "[Hypertext Cache Pattern][hcp]".
269
+
270
+ When you enable `hcp`, the library detects if a requested resource is already
271
+ embedded, and will use that resource as a mocked response, eliminating any extra
272
+ request to get the resource:
273
+
274
+ ```ruby
275
+ pump = product.rel('pump', hcp: true).get
276
+
277
+ pump[:hcp] # => true
278
+ pump.remote_ip # => '127.0.0.1'
279
+ pump.resource.weight # => '2kg'
280
+ ```
281
+
282
+ This feature only works if you are sure the embedded resource is equal to the
283
+ resource returned by the link relation. Because of this requirement, the default
284
+ configuration has `hcp` disabled, you can either enable it per request (which
285
+ also enables it for future requests in the chain), or enable it globally:
286
+
287
+ ```ruby
288
+ Excon.defaults[:hcp] = true
289
+ ```
290
+
291
+ ### shortcuts
292
+
293
+ While the above examples shows the clean separation between the different
294
+ concepts like `response`, `resource`, `links`, `properties` and `emeds`.
295
+
296
+ Traversing these objects always starts from the response object. To make moving
297
+ around a bit faster, there are several methods available on the
298
+ `Excon::Response` object for ease-of-use:
299
+
300
+ ```ruby
301
+ product.links.class # => Excon::HyperMedia::ResourceObject::Links
302
+ product.properties.class # => Excon::HyperMedia::ResourceObject::Properties
303
+ product.embedded.class # => Excon::HyperMedia::ResourceObject::Embedded
259
304
  ```
260
305
 
261
306
  ## License
@@ -267,3 +312,4 @@ The gem is available as open source under the terms of the [MIT License](http://
267
312
  [excon-addressable]: https://github.com/JeanMertz/excon-addressable
268
313
  [options]: https://github.com/excon/excon#options
269
314
  [_embedded]: https://tools.ietf.org/html/draft-kelly-json-hal-08#section-4.1.2
315
+ [hcp]: https://tools.ietf.org/html/draft-kelly-json-hal-06#section-8.3
@@ -17,13 +17,14 @@ Gem::Specification.new do |spec|
17
17
  spec.files = `git ls-files -z`.split("\x0")
18
18
  spec.require_paths = %w(lib)
19
19
 
20
- spec.add_development_dependency 'bundler', '~> 1.12'
20
+ spec.add_development_dependency 'bundler', '~> 1.9'
21
21
  spec.add_development_dependency 'rake', '~> 10.0'
22
22
  spec.add_development_dependency 'minitest', '~> 5.0'
23
23
  spec.add_development_dependency 'rubocop', '~> 0.40'
24
24
  spec.add_development_dependency 'pry', '~> 0.10'
25
25
  spec.add_development_dependency 'm', '~> 1.5'
26
26
 
27
+ spec.add_dependency 'backport_dig' if RUBY_VERSION < '2.3'
27
28
  spec.add_dependency 'excon', '~> 0.49'
28
29
  spec.add_dependency 'excon-addressable', '~> 0.3'
29
30
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :no-doc:
4
+ module Excon
5
+ module HyperMedia
6
+ class Error < StandardError; end
7
+
8
+ UnknownRelationError = Class.new(Error)
9
+ end
10
+ end
@@ -12,7 +12,7 @@ module Excon
12
12
  include Enumerable
13
13
 
14
14
  def initialize(collection = {})
15
- @collection ||= collection
15
+ @collection ||= collection.to_h
16
16
  to_properties
17
17
  end
18
18
 
@@ -34,6 +34,21 @@ module Excon
34
34
 
35
35
  private
36
36
 
37
+ # method_missing
38
+ #
39
+ # Collections can be accessed using both the "dot notation" and the hash
40
+ # notation:
41
+ #
42
+ # collection.hello_world
43
+ # collection['hello_world']
44
+ #
45
+ # The second notation returns `nil` on missing keys, the first should do
46
+ # as well.
47
+ #
48
+ def method_missing(_)
49
+ nil
50
+ end
51
+
37
52
  def to_properties
38
53
  collection.each do |key, value|
39
54
  key = key.downcase
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'backport_dig' if RUBY_VERSION < '2.3'
4
+
3
5
  Excon.defaults[:middlewares].delete(Excon::Addressable::Middleware)
4
6
  Excon.defaults[:middlewares].unshift(Excon::Addressable::Middleware)
5
7
 
@@ -14,6 +16,12 @@ module Excon
14
16
  # will be left alone by this middleware.
15
17
  #
16
18
  class Middleware < Excon::Middleware::Base
19
+ def request_call(datum)
20
+ orig_stack = @stack
21
+ @stack = Excon::HyperMedia::Middlewares::HypertextCachePattern.new(orig_stack)
22
+ super
23
+ end
24
+
17
25
  def response_call(datum)
18
26
  return super unless (content_type = datum.dig(:response, :headers, 'Content-Type').to_s)
19
27
 
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Excon
4
+ module HyperMedia
5
+ module Middlewares
6
+ # HypertextCachePattern
7
+ #
8
+ # This middleware handles hcp-enabled requests.
9
+ #
10
+ # @see: https://tools.ietf.org/html/draft-kelly-json-hal-06#section-8.3
11
+ #
12
+ class HypertextCachePattern < Excon::Middleware::Base
13
+ attr_reader :datum
14
+
15
+ def request_call(datum)
16
+ @datum = datum
17
+
18
+ return super unless datum[:hcp] == true && datum[:method] == :get && find_embedded
19
+
20
+ datum[:response] = {
21
+ body: @embedded.to_json,
22
+ hcp: true,
23
+ headers: content_type_header,
24
+ remote_ip: '127.0.0.1',
25
+ status: 200
26
+ }
27
+
28
+ super
29
+ end
30
+
31
+ private
32
+
33
+ def find_embedded
34
+ datum.dig(:hcp_params, :embedded).to_h.each do |_, object|
35
+ break if (@embedded = object_to_embedded(object))
36
+ end
37
+
38
+ @embedded
39
+ end
40
+
41
+ def object_to_embedded(object)
42
+ uri = ::Addressable::URI.new(datum.tap { |h| h.delete(:port) })
43
+
44
+ if object.respond_to?(:to_ary)
45
+ object.find { |hash| hash.dig('_links', 'self', 'href') == uri.to_s }
46
+ elsif object.dig('_links', 'self', 'href') == uri.to_s
47
+ object
48
+ end
49
+ end
50
+
51
+ def content_type_header
52
+ return {} unless (header = datum.dig(:hcp_params, :content_type))
53
+
54
+ { 'Content-Type' => header }
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -15,14 +15,6 @@ module Excon
15
15
 
16
16
  def initialize(data)
17
17
  @data = data
18
-
19
- _properties.each do |key, value|
20
- key = key.downcase
21
- next unless /[@$"]/ !~ key.to_sym.inspect
22
-
23
- singleton_class.class_eval { attr_reader key }
24
- instance_variable_set("@#{key}", value.respond_to?(:keys) ? Properties.new(value) : value)
25
- end
26
18
  end
27
19
 
28
20
  def _properties
@@ -64,6 +56,10 @@ module Excon
64
56
  def [](key)
65
57
  _properties[key]
66
58
  end
59
+
60
+ def method_missing(method_name, *_)
61
+ _properties.send(method_name)
62
+ end
67
63
  end
68
64
  end
69
65
  end
@@ -18,12 +18,15 @@ module Excon
18
18
  #
19
19
  # Correctly handle the hypermedia request.
20
20
  #
21
- def handle(method_name, *params)
21
+ def handle(method_name, *params) # rubocop:disable Metrics/CyclomaticComplexity
22
22
  return false unless enabled?
23
23
 
24
24
  case method_name
25
- when :resource then resource
26
- when :rel then rel(params.shift, params)
25
+ when :resource then resource
26
+ when :_links, :links then resource._links
27
+ when :_embedded, :embedded then resource._embedded
28
+ when :_properties, :properties then resource._properties
29
+ when :rel then rel(params.shift, params)
27
30
  else false
28
31
  end
29
32
  end
@@ -49,11 +52,27 @@ module Excon
49
52
  end
50
53
 
51
54
  def rel(name, params)
52
- link = resource._links.send(name)
53
- options = params.first.to_h.merge(hypermedia: true)
55
+ raise ArgumentError, 'missing relation name' unless name
56
+
57
+ unless (link = resource._links[name])
58
+ raise UnknownRelationError, "unknown relation: #{name}"
59
+ end
60
+
61
+ options = rel_params(params.first.to_h)
54
62
 
55
63
  link.respond_to?(:to_ary) ? link.map { |l| l.rel(options) } : link.rel(options)
56
64
  end
65
+
66
+ def rel_params(params)
67
+ params.merge(
68
+ hypermedia: true,
69
+ hcp: (params[:hcp].nil? ? response.data[:hcp] : params[:hcp]),
70
+ hcp_params: {
71
+ content_type: response.headers['Content-Type'],
72
+ embedded: resource._embedded
73
+ }
74
+ )
75
+ end
57
76
  end
58
77
  end
59
78
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Excon
4
4
  module HyperMedia
5
- VERSION = '0.4.3'
5
+ VERSION = '0.5.0'
6
6
  end
7
7
  end
@@ -3,9 +3,11 @@
3
3
  require 'excon'
4
4
  require 'excon/addressable'
5
5
 
6
+ require 'excon/hypermedia/errors'
6
7
  require 'excon/hypermedia/helpers/collection'
7
8
  require 'excon/hypermedia/link_object'
8
9
  require 'excon/hypermedia/middleware'
10
+ require 'excon/hypermedia/middlewares/hypertext_cache_pattern'
9
11
  require 'excon/hypermedia/resource_object'
10
12
  require 'excon/hypermedia/response'
11
13
  require 'excon/hypermedia/version'
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../test_helper'
4
+
5
+ module Excon
6
+ # EdgeCaseTest
7
+ #
8
+ # Validate edge cases (or: non-happy path)
9
+ #
10
+ class EdgeCaseTest < HyperMediaTest
11
+ def setup
12
+ Excon.defaults[:mock] = true
13
+ Excon.defaults[:middlewares].push(Excon::HyperMedia::Middleware)
14
+
15
+ response = { headers: { 'Content-Type' => 'application/hal+json' } }
16
+ Excon.stub({ path: '/api.json' }, response.merge(body: api_body))
17
+ Excon.stub({ path: '/empty_json' }, response.merge(body: '{}'))
18
+ end
19
+
20
+ def teardown
21
+ Excon.stubs.clear
22
+ Excon.defaults[:middlewares].delete(Excon::HyperMedia::Middleware)
23
+ end
24
+
25
+ def api
26
+ Excon.get('https://www.example.org/api.json')
27
+ end
28
+
29
+ def test_missing_middleware
30
+ Excon.defaults[:middlewares].delete(Excon::HyperMedia::Middleware)
31
+
32
+ assert_raises(NoMethodError) { api.rel }
33
+ end
34
+
35
+ def test_rel_missing_name
36
+ ex = assert_raises(ArgumentError) { api.rel }
37
+ assert_equal 'missing relation name', ex.message
38
+ end
39
+
40
+ def test_rel_missing_arguments
41
+ assert_equal Excon::Connection, api.rel('self').class
42
+ end
43
+
44
+ def test_rel_unknown_relation
45
+ ex = assert_raises(Excon::HyperMedia::UnknownRelationError) { api.rel('invalid') }
46
+ assert_equal 'unknown relation: invalid', ex.message
47
+ end
48
+
49
+ def test_missing_links
50
+ resource = Excon.get('https://www.example.org/empty_json').resource
51
+
52
+ assert_equal({}, resource._links.to_h)
53
+ end
54
+
55
+ def test_missing_embedded
56
+ resource = Excon.get('https://www.example.org/empty_json').resource
57
+
58
+ assert_equal({}, resource._embedded.to_h)
59
+ end
60
+
61
+ def test_missing_properties
62
+ resource = Excon.get('https://www.example.org/empty_json').resource
63
+
64
+ assert_equal({}, resource._properties.to_h)
65
+ end
66
+
67
+ def test_unknown_property
68
+ resource = Excon.get('https://www.example.org/api.json').resource
69
+
70
+ assert_equal nil, resource._properties.invalid
71
+ assert_equal nil, resource._properties['invalid']
72
+ end
73
+
74
+ def test_unknown_link
75
+ resource = Excon.get('https://www.example.org/empty_json').resource
76
+
77
+ assert_equal nil, resource._links.invalid
78
+ assert_equal nil, resource._links['invalid']
79
+ end
80
+
81
+ def test_unknown_embed
82
+ resource = Excon.get('https://www.example.org/api.json').resource
83
+
84
+ assert_equal nil, resource._embedded.invalid
85
+ assert_equal nil, resource._embedded['invalid']
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../test_helper'
4
+
5
+ module Excon
6
+ # HCPTest
7
+ #
8
+ # Validate the workings of `Excon::HyperResource::Middlewares::HypertextCachePattern`.
9
+ #
10
+ class HCPTest < HyperMediaTest
11
+ def response
12
+ @response ||= Excon.get('https://example.org/product/bicycle')
13
+ end
14
+
15
+ def test_non_hcp_response
16
+ assert_equal nil, response[:hcp]
17
+ end
18
+
19
+ def test_hcp_response
20
+ assert response.rel('pump', hcp: true).get[:hcp]
21
+ end
22
+
23
+ def test_hcp_response_with_missing_embedding
24
+ api = Excon.get('https://www.example.org/api.json')
25
+ response = api.rel('product', expand: { uid: 'bicycle' }, rel: true).get
26
+
27
+ assert_equal nil, response[:hcp]
28
+ end
29
+
30
+ def test_hcp_response_with_embedded_array
31
+ wheels = response.rel('wheels', hcp: true)
32
+
33
+ assert wheels.map(&:get).all? { |res| res[:hcp] }
34
+ end
35
+
36
+ def test_nested_hcp_responses
37
+ pump = response.rel('pump', hcp: true).get
38
+ response = pump.rel('parts', expand: { uid: 'bicycle' }).get
39
+
40
+ assert response[:hcp]
41
+ end
42
+
43
+ def test_hcp_not_working_for_non_get_requests
44
+ assert_equal nil, response.rel('pump', hcp: true).post[:hcp]
45
+ end
46
+
47
+ def test_hcp_resource
48
+ resource = response.rel('pump', hcp: true).get.resource
49
+
50
+ assert_equal Excon::HyperMedia::ResourceObject, resource.class
51
+ end
52
+
53
+ def test_hcp_links
54
+ resource = response.rel('pump', hcp: true).get.resource
55
+
56
+ assert_equal data(:parts)['_links']['self']['href'], resource._links.parts.href
57
+ end
58
+ end
59
+ end
@@ -48,10 +48,6 @@ module Excon
48
48
  assert response.body.include?('https://www.example.org/product/bicycle')
49
49
  end
50
50
 
51
- def test_invalid_relation
52
- assert_raises(NoMethodError) { api.rel('invalid') }
53
- end
54
-
55
51
  def test_link
56
52
  response = api.rel('product', expand: { uid: 'bicycle' }).get
57
53
 
@@ -18,7 +18,7 @@ module Excon
18
18
  end
19
19
 
20
20
  def full
21
- <<~EOF
21
+ <<-EOF
22
22
  {
23
23
  "href": "https://www.example.org/goodbye/{receiver}",
24
24
  "templated": "true",
@@ -10,7 +10,7 @@ module Excon
10
10
  #
11
11
  class LinksTest < Minitest::Test
12
12
  def body
13
- <<~EOF
13
+ <<-EOF
14
14
  {
15
15
  "_links": {
16
16
  "self": {
@@ -10,7 +10,7 @@ module Excon
10
10
  #
11
11
  class PropertiesTest < Minitest::Test
12
12
  def body
13
- <<~EOF
13
+ <<-EOF
14
14
  {
15
15
  "size": "49CM",
16
16
  "bike-type": "Mountain Bike",
@@ -10,7 +10,7 @@ module Excon
10
10
  #
11
11
  class ResourceObjectTest < Minitest::Test
12
12
  def body
13
- <<~EOF
13
+ <<-EOF
14
14
  {
15
15
  "_links": {
16
16
  "hello": {
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../test_helper'
4
+
5
+ module Excon
6
+ # ResourceObjectTest
7
+ #
8
+ # Validate the workings of `Excon::HyperResource::ResourceObject`.
9
+ #
10
+ class ResponseTest < HyperMediaTest
11
+ def response
12
+ @response ||= Excon.get('https://example.org/product/bicycle')
13
+ end
14
+
15
+ def test_response
16
+ assert_equal Excon::Response, response.class
17
+ end
18
+
19
+ def test_links
20
+ assert_equal response.resource._links, response.links
21
+ assert_equal response.resource._links, response._links
22
+ end
23
+
24
+ def test_embedded
25
+ assert_equal response.resource._embedded, response.embedded
26
+ assert_equal response.resource._embedded, response._embedded
27
+ end
28
+
29
+ def test_properties
30
+ assert_equal response.resource._properties, response.properties
31
+ assert_equal response.resource._properties, response._properties
32
+ end
33
+ end
34
+ end
data/test/test_helper.rb CHANGED
@@ -21,7 +21,8 @@ module Excon
21
21
  Excon.stub({ method: :get, path: '/product/bicycle' }, response.merge(body: bicycle_body))
22
22
  Excon.stub({ method: :get, path: '/product/bicycle/wheels/front' }, response.merge(body: front_wheel_body))
23
23
  Excon.stub({ method: :get, path: '/product/bicycle/wheels/rear' }, response.merge(body: rear_wheel_body))
24
- Excon.stub({ method: :get, path: '/product/pump' }, response.merge(body: pump_body))
24
+ Excon.stub({ path: '/product/pump' }, response.merge(body: pump_body))
25
+ Excon.stub({ method: :get, path: '/product/pump/parts' }, response.merge(body: parts_body))
25
26
  Excon.stub({ method: :get, path: '/product/handlebar' }, response.merge(body: handlebar_body))
26
27
  Excon.stub({ method: :get, path: '/api_v2.json' }, body: api_body, headers: { 'Content-Type' => 'application/json' })
27
28
  end
@@ -37,7 +38,7 @@ module Excon
37
38
  end
38
39
 
39
40
  def api_body
40
- <<~EOF
41
+ <<-EOF
41
42
  {
42
43
  "_links": {
43
44
  "self": {
@@ -53,7 +54,7 @@ module Excon
53
54
  end
54
55
 
55
56
  def bicycle_body
56
- <<~EOF
57
+ <<-EOF
57
58
  {
58
59
  "_links": {
59
60
  "self": {
@@ -90,7 +91,7 @@ module Excon
90
91
  end
91
92
 
92
93
  def handlebar_body
93
- <<~EOF
94
+ <<-EOF
94
95
  {
95
96
  "_links": {
96
97
  "self": {
@@ -105,22 +106,42 @@ module Excon
105
106
  end
106
107
 
107
108
  def pump_body
108
- <<~EOF
109
+ <<-EOF
109
110
  {
110
111
  "_links": {
111
112
  "self": {
112
113
  "href": "https://www.example.org/product/pump"
114
+ },
115
+ "parts": {
116
+ "href": "https://www.example.org/product/pump/parts"
113
117
  }
114
118
  },
115
119
  "weight": "2kg",
116
120
  "type": "Floor Pump",
117
- "valve-type": "Presta"
121
+ "valve-type": "Presta",
122
+ "_embedded": {
123
+ "parts": #{parts_body}
124
+ }
125
+
126
+ }
127
+ EOF
128
+ end
129
+
130
+ def parts_body
131
+ <<-EOF
132
+ {
133
+ "_links": {
134
+ "self": {
135
+ "href": "https://www.example.org/product/pump/parts"
136
+ }
137
+ },
138
+ "count": 47
118
139
  }
119
140
  EOF
120
141
  end
121
142
 
122
143
  def rear_wheel_body
123
- <<~EOF
144
+ <<-EOF
124
145
  {
125
146
  "_links": {
126
147
  "self": {
@@ -134,7 +155,7 @@ module Excon
134
155
  end
135
156
 
136
157
  def front_wheel_body
137
- <<~EOF
158
+ <<-EOF
138
159
  {
139
160
  "_links": {
140
161
  "self": {
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: excon-hypermedia
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-05-27 00:00:00.000000000 Z
12
+ date: 2016-05-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -17,14 +17,14 @@ dependencies:
17
17
  requirements:
18
18
  - - "~>"
19
19
  - !ruby/object:Gem::Version
20
- version: '1.12'
20
+ version: '1.9'
21
21
  type: :development
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - "~>"
26
26
  - !ruby/object:Gem::Version
27
- version: '1.12'
27
+ version: '1.9'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: rake
30
30
  requirement: !ruby/object:Gem::Requirement
@@ -140,21 +140,26 @@ files:
140
140
  - Rakefile
141
141
  - excon-hypermedia.gemspec
142
142
  - lib/excon/hypermedia.rb
143
+ - lib/excon/hypermedia/errors.rb
143
144
  - lib/excon/hypermedia/ext/response.rb
144
145
  - lib/excon/hypermedia/helpers/collection.rb
145
146
  - lib/excon/hypermedia/link_object.rb
146
147
  - lib/excon/hypermedia/middleware.rb
148
+ - lib/excon/hypermedia/middlewares/hypertext_cache_pattern.rb
147
149
  - lib/excon/hypermedia/resource_object.rb
148
150
  - lib/excon/hypermedia/resource_object/embedded.rb
149
151
  - lib/excon/hypermedia/resource_object/links.rb
150
152
  - lib/excon/hypermedia/resource_object/properties.rb
151
153
  - lib/excon/hypermedia/response.rb
152
154
  - lib/excon/hypermedia/version.rb
155
+ - test/excon/edgecase_test.rb
156
+ - test/excon/hcp_test.rb
153
157
  - test/excon/integration_test.rb
154
158
  - test/excon/link_object_test.rb
155
159
  - test/excon/links_test.rb
156
160
  - test/excon/properties_test.rb
157
161
  - test/excon/resource_object_test.rb
162
+ - test/excon/response_test.rb
158
163
  - test/test_helper.rb
159
164
  homepage: https://github.com/JeanMertz/excon-hypermedia
160
165
  licenses: