excon-hypermedia 0.3.0 → 0.4.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 +4 -4
- data/README.md +194 -30
- data/lib/excon/hypermedia/ext/response.rb +2 -0
- data/lib/excon/hypermedia/helpers/collection.rb +62 -0
- data/lib/excon/hypermedia/link_object.rb +153 -0
- data/lib/excon/hypermedia/middleware.rb +2 -0
- data/lib/excon/hypermedia/resource_object/embedded.rb +23 -0
- data/lib/excon/hypermedia/resource_object/links.rb +19 -0
- data/lib/excon/hypermedia/resource_object/properties.rb +17 -0
- data/lib/excon/hypermedia/resource_object.rb +69 -0
- data/lib/excon/hypermedia/response.rb +18 -11
- data/lib/excon/hypermedia/version.rb +1 -1
- data/lib/excon/hypermedia.rb +4 -2
- data/test/excon/integration_test.rb +99 -0
- data/test/excon/link_object_test.rb +91 -0
- data/test/excon/links_test.rb +43 -0
- data/test/excon/properties_test.rb +67 -0
- data/test/excon/resource_object_test.rb +49 -0
- data/test/test_helper.rb +141 -0
- metadata +13 -7
- data/lib/excon/hypermedia/link.rb +0 -40
- data/lib/excon/hypermedia/resource.rb +0 -49
- data/test/excon/hypermedia_test.rb +0 -100
- data/test/excon/link_test.rb +0 -56
- data/test/excon/resource_test.rb +0 -47
@@ -21,14 +21,10 @@ module Excon
|
|
21
21
|
def handle(method_name, *params)
|
22
22
|
return false unless enabled?
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
elsif resource.respond_to?(method_name, false)
|
29
|
-
resource.send(method_name, *params)
|
30
|
-
else
|
31
|
-
false
|
24
|
+
case method_name
|
25
|
+
when :resource then resource
|
26
|
+
when :rel then rel(params.shift, params)
|
27
|
+
else false
|
32
28
|
end
|
33
29
|
end
|
34
30
|
|
@@ -37,15 +33,26 @@ module Excon
|
|
37
33
|
attr_reader :response
|
38
34
|
|
39
35
|
def resource
|
40
|
-
@resource ||=
|
36
|
+
@resource ||= ResourceObject.new(body_to_hash)
|
37
|
+
end
|
38
|
+
|
39
|
+
def body_to_hash
|
40
|
+
content_type.include?('application/hal+json') ? JSON.parse(response.body) : {}
|
41
|
+
end
|
42
|
+
|
43
|
+
def content_type
|
44
|
+
response.headers['Content-Type'].to_s
|
41
45
|
end
|
42
46
|
|
43
47
|
def enabled?
|
44
48
|
response.data[:hypermedia] == true
|
45
49
|
end
|
46
50
|
|
47
|
-
def
|
48
|
-
|
51
|
+
def rel(name, params)
|
52
|
+
link = resource._links.send(name)
|
53
|
+
options = params.first.to_h.merge(hypermedia: true)
|
54
|
+
|
55
|
+
link.respond_to?(:to_ary) ? link.map { |l| l.rel(options) } : link.rel(options)
|
49
56
|
end
|
50
57
|
end
|
51
58
|
end
|
data/lib/excon/hypermedia.rb
CHANGED
@@ -2,8 +2,10 @@
|
|
2
2
|
|
3
3
|
require 'excon'
|
4
4
|
require 'excon/addressable'
|
5
|
-
|
5
|
+
|
6
|
+
require 'excon/hypermedia/helpers/collection'
|
7
|
+
require 'excon/hypermedia/link_object'
|
6
8
|
require 'excon/hypermedia/middleware'
|
7
|
-
require 'excon/hypermedia/
|
9
|
+
require 'excon/hypermedia/resource_object'
|
8
10
|
require 'excon/hypermedia/response'
|
9
11
|
require 'excon/hypermedia/version'
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# rubocop:disable Metrics/AbcSize
|
3
|
+
# rubocop:disable Metrics/LineLength
|
4
|
+
|
5
|
+
require_relative '../test_helper'
|
6
|
+
|
7
|
+
module Excon
|
8
|
+
# IntegrationTest
|
9
|
+
#
|
10
|
+
# Verifies the Excon connection consuming HyperMedia APIs.
|
11
|
+
#
|
12
|
+
class IntegrationTest < HyperMediaTest
|
13
|
+
def api
|
14
|
+
Excon.get('https://www.example.org/api.json')
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_request
|
18
|
+
response = api.rel('product', expand: { uid: 'bicycle' }).get
|
19
|
+
|
20
|
+
assert response.body.include?('https://www.example.org/product/bicycle')
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_request_using_link_rel
|
24
|
+
response = api.resource._links.product.rel(expand: { uid: 'bicycle' }).get
|
25
|
+
|
26
|
+
assert response.body.include?('https://www.example.org/product/bicycle')
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_nested_request
|
30
|
+
bicycle = api.rel('product', expand: { uid: 'bicycle' }).get
|
31
|
+
response = bicycle.rel('handlebar').get
|
32
|
+
|
33
|
+
assert_equal data(:handlebar)['material'], response.resource.material
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_collection_request
|
37
|
+
bicycle = api.rel('product', expand: { uid: 'bicycle' }).get
|
38
|
+
wheels = bicycle.rel('wheels')
|
39
|
+
responses = wheels.map(&:get)
|
40
|
+
|
41
|
+
assert Array, wheels.class
|
42
|
+
assert_equal data(:front_wheel)['position'], responses.first.resource.position
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_expand_in_get
|
46
|
+
response = api.rel('product').get(expand: { uid: 'bicycle' })
|
47
|
+
|
48
|
+
assert response.body.include?('https://www.example.org/product/bicycle')
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_invalid_relation
|
52
|
+
assert_raises(NoMethodError) { api.rel('invalid') }
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_link
|
56
|
+
response = api.rel('product', expand: { uid: 'bicycle' }).get
|
57
|
+
|
58
|
+
assert_equal data(:bicycle)['_links']['handlebar']['href'], response.resource._links.handlebar.href
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_link_collection
|
62
|
+
response = api.rel('product', expand: { uid: 'bicycle' }).get
|
63
|
+
|
64
|
+
assert_equal Array, response.resource._links.wheels.class
|
65
|
+
assert_equal data(:bicycle)['_links']['wheels'][0]['href'], response.resource._links.wheels.first.href
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_nested_attributes
|
69
|
+
response = api.rel('product', expand: { uid: 'bicycle' }).get
|
70
|
+
|
71
|
+
assert_equal 7, response.resource.derailleurs.back
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_invalid_attribute
|
75
|
+
response = api.rel('product', expand: { uid: 'bicycle' }).get
|
76
|
+
|
77
|
+
assert_equal 'Mountain Bike', response.resource['bike-type']
|
78
|
+
assert_equal false, response.resource.bmx
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_embedded_resource
|
82
|
+
response = api.rel('product', expand: { uid: 'bicycle' }).get
|
83
|
+
|
84
|
+
assert_equal Excon::HyperMedia::ResourceObject, response.resource._embedded.pump.class
|
85
|
+
assert_equal '2kg', response.resource._embedded.pump.weight
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_embedded_resource_collection
|
89
|
+
response = api.rel('product', expand: { uid: 'bicycle' }).get
|
90
|
+
|
91
|
+
assert_equal Array, response.resource._embedded.wheels.class
|
92
|
+
assert_equal data(:front_wheel)['position'], response.resource._embedded.wheels.first.position
|
93
|
+
end
|
94
|
+
|
95
|
+
def teardown
|
96
|
+
Excon.stubs.clear
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# rubocop:disable Metrics/MethodLength
|
3
|
+
|
4
|
+
require_relative '../test_helper'
|
5
|
+
|
6
|
+
module Excon
|
7
|
+
# LinkTest
|
8
|
+
#
|
9
|
+
# Validate the workings of `Excon::HyperResource::LinkObject`.
|
10
|
+
#
|
11
|
+
class LinkTest < Minitest::Test
|
12
|
+
def self
|
13
|
+
'{ "href": "https://www.example.org/hello" }'
|
14
|
+
end
|
15
|
+
|
16
|
+
def templated
|
17
|
+
'{ "href": "https://www.example.org/hello/{receiver}", "templated": "true" }'
|
18
|
+
end
|
19
|
+
|
20
|
+
def full
|
21
|
+
<<~EOF
|
22
|
+
{
|
23
|
+
"href": "https://www.example.org/goodbye/{receiver}",
|
24
|
+
"templated": "true",
|
25
|
+
"type": "json",
|
26
|
+
"deprecation": true,
|
27
|
+
"name": "goodbye",
|
28
|
+
"profile": "https://profile.example.org",
|
29
|
+
"title": "Goodbye!",
|
30
|
+
"hreflang": "en-gb"
|
31
|
+
}
|
32
|
+
EOF
|
33
|
+
end
|
34
|
+
|
35
|
+
def data(name)
|
36
|
+
JSON.parse(send(name))
|
37
|
+
end
|
38
|
+
|
39
|
+
def link(name)
|
40
|
+
Excon::HyperMedia::LinkObject.new(data(name))
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_link
|
44
|
+
assert_equal data(:self), link(:self).to_h
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_missing_property
|
48
|
+
assert_raises(NoMethodError) { data(:self).name }
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_href
|
52
|
+
assert_equal data(:self)['href'], link(:self).href
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_templated
|
56
|
+
assert link(:templated).templated
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_templated_returns_false_if_undefined
|
60
|
+
refute link(:self).templated
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_type
|
64
|
+
assert_equal data(:full)['type'], link(:full).type
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_deprecation
|
68
|
+
assert_equal data(:full)['deprecation'], link(:full).deprecation
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_name
|
72
|
+
assert_equal data(:full)['name'], link(:full).name
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_profile
|
76
|
+
assert_equal data(:full)['profile'], link(:full).profile
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_title
|
80
|
+
assert_equal data(:full)['title'], link(:full).title
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_hreflang
|
84
|
+
assert_equal data(:full)['hreflang'], link(:full).hreflang
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_uri
|
88
|
+
assert_equal data(:self)['href'], link(:self).uri.to_s
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# rubocop:disable Metrics/MethodLength
|
3
|
+
|
4
|
+
require_relative '../test_helper'
|
5
|
+
|
6
|
+
module Excon
|
7
|
+
# LinksTest
|
8
|
+
#
|
9
|
+
# Validate the workings of `Excon::HyperResource::Resource::Links`.
|
10
|
+
#
|
11
|
+
class LinksTest < Minitest::Test
|
12
|
+
def body
|
13
|
+
<<~EOF
|
14
|
+
{
|
15
|
+
"_links": {
|
16
|
+
"self": {
|
17
|
+
"href": "https://www.example.org/product/bicycle"
|
18
|
+
},
|
19
|
+
"parts": {
|
20
|
+
"href": "https://www.example.org/product/bicycle/parts"
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|
24
|
+
EOF
|
25
|
+
end
|
26
|
+
|
27
|
+
def data
|
28
|
+
JSON.parse(body)
|
29
|
+
end
|
30
|
+
|
31
|
+
def links
|
32
|
+
@links ||= Excon::HyperMedia::ResourceObject::Links.new(data['_links'])
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_links
|
36
|
+
assert_equal Excon::HyperMedia::ResourceObject::Links, links.class
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_link_properties
|
40
|
+
assert_equal %w(self parts), links.to_h.keys
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# rubocop:disable Metrics/MethodLength
|
3
|
+
|
4
|
+
require_relative '../test_helper'
|
5
|
+
|
6
|
+
module Excon
|
7
|
+
# PropertiesTest
|
8
|
+
#
|
9
|
+
# Validate the workings of `Excon::HyperResource::Resource::Properties`.
|
10
|
+
#
|
11
|
+
class PropertiesTest < Minitest::Test
|
12
|
+
def body
|
13
|
+
<<~EOF
|
14
|
+
{
|
15
|
+
"size": "49CM",
|
16
|
+
"bike-type": "Mountain Bike",
|
17
|
+
"derailleurs": {
|
18
|
+
"front": 3,
|
19
|
+
"back": 7
|
20
|
+
},
|
21
|
+
"reflectors": true,
|
22
|
+
"BMX": false
|
23
|
+
}
|
24
|
+
EOF
|
25
|
+
end
|
26
|
+
|
27
|
+
def data
|
28
|
+
JSON.parse(body)
|
29
|
+
end
|
30
|
+
|
31
|
+
def properties
|
32
|
+
@properties ||= Excon::HyperMedia::ResourceObject::Properties.new(data)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_properties
|
36
|
+
assert_equal data, properties.to_h
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_attribute
|
40
|
+
assert_equal properties.size, '49CM'
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_boolean_attribute
|
44
|
+
assert_equal properties.reflectors, true
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_uppercase_attribute_names
|
48
|
+
assert_equal properties.bmx, false
|
49
|
+
assert_equal properties['BMX'], false
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_invalid_attribute_names
|
53
|
+
refute properties.respond_to?('bike-type')
|
54
|
+
assert_equal properties['bike-type'], 'Mountain Bike'
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_nested_attribute
|
58
|
+
assert_equal properties.derailleurs.front, 3
|
59
|
+
assert_equal properties.derailleurs.back, 7
|
60
|
+
assert_equal properties['derailleurs'].back, 7
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_nested_attribute_hash
|
64
|
+
assert_equal properties.derailleurs.to_h, data['derailleurs']
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# rubocop:disable Metrics/MethodLength
|
3
|
+
|
4
|
+
require_relative '../test_helper'
|
5
|
+
|
6
|
+
module Excon
|
7
|
+
# ResourceObjectTest
|
8
|
+
#
|
9
|
+
# Validate the workings of `Excon::HyperResource::ResourceObject`.
|
10
|
+
#
|
11
|
+
class ResourceObjectTest < Minitest::Test
|
12
|
+
def body
|
13
|
+
<<~EOF
|
14
|
+
{
|
15
|
+
"_links": {
|
16
|
+
"hello": {
|
17
|
+
"href": "http://www.example.com/hello/{location}"
|
18
|
+
}
|
19
|
+
},
|
20
|
+
"uid": "universe",
|
21
|
+
"hello": "world"
|
22
|
+
}
|
23
|
+
EOF
|
24
|
+
end
|
25
|
+
|
26
|
+
def data
|
27
|
+
@data ||= JSON.parse(body)
|
28
|
+
end
|
29
|
+
|
30
|
+
def resource
|
31
|
+
@resource ||= Excon::HyperMedia::ResourceObject.new(data)
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_resource
|
35
|
+
assert_equal data, resource.instance_variable_get(:@data)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_links
|
39
|
+
assert_equal data['_links']['hello']['href'], resource._links.hello.href
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_properties
|
43
|
+
assert_equal 'universe', resource.uid
|
44
|
+
assert_equal 'world', resource.hello
|
45
|
+
assert_equal 'world', resource['hello']
|
46
|
+
assert_equal nil, resource['invalid']
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -1,4 +1,145 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
# rubocop:disable Metrics/MethodLength
|
3
|
+
# rubocop:disable Metrics/LineLength
|
4
|
+
# rubocop:disable Metrics/ClassLength
|
5
|
+
# rubocop:disable Metrics/AbcSize
|
6
|
+
|
2
7
|
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
3
8
|
require 'excon/hypermedia'
|
4
9
|
require 'minitest/autorun'
|
10
|
+
|
11
|
+
module Excon
|
12
|
+
# HyperMediaTest
|
13
|
+
#
|
14
|
+
class HyperMediaTest < Minitest::Test
|
15
|
+
def setup
|
16
|
+
Excon.defaults[:mock] = true
|
17
|
+
Excon.defaults[:middlewares].push(Excon::HyperMedia::Middleware)
|
18
|
+
|
19
|
+
response = { headers: { 'Content-Type' => 'application/hal+json' } }
|
20
|
+
Excon.stub({ method: :get, path: '/api.json' }, response.merge(body: api_body))
|
21
|
+
Excon.stub({ method: :get, path: '/product/bicycle' }, response.merge(body: bicycle_body))
|
22
|
+
Excon.stub({ method: :get, path: '/product/bicycle/wheels/front' }, response.merge(body: front_wheel_body))
|
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))
|
25
|
+
Excon.stub({ method: :get, path: '/product/handlebar' }, response.merge(body: handlebar_body))
|
26
|
+
end
|
27
|
+
|
28
|
+
def teardown
|
29
|
+
Excon.stubs.clear
|
30
|
+
Excon.defaults[:middlewares].delete(Excon::HyperMedia::Middleware)
|
31
|
+
Excon.defaults[:mock] = true
|
32
|
+
end
|
33
|
+
|
34
|
+
def data(name)
|
35
|
+
JSON.parse(send("#{name}_body"))
|
36
|
+
end
|
37
|
+
|
38
|
+
def api_body
|
39
|
+
<<~EOF
|
40
|
+
{
|
41
|
+
"_links": {
|
42
|
+
"self": {
|
43
|
+
"href": "https://www.example.org/api.json"
|
44
|
+
},
|
45
|
+
"product": {
|
46
|
+
"href": "https://www.example.org/product/{uid}",
|
47
|
+
"templated": true
|
48
|
+
}
|
49
|
+
}
|
50
|
+
}
|
51
|
+
EOF
|
52
|
+
end
|
53
|
+
|
54
|
+
def bicycle_body
|
55
|
+
<<~EOF
|
56
|
+
{
|
57
|
+
"_links": {
|
58
|
+
"self": {
|
59
|
+
"href": "https://www.example.org/product/bicycle"
|
60
|
+
},
|
61
|
+
"handlebar": {
|
62
|
+
"href": "https://www.example.org/product/handlebar"
|
63
|
+
},
|
64
|
+
"object_id": {
|
65
|
+
"href": "https://www.example.org/product/bicycle/object_id_as_text"
|
66
|
+
},
|
67
|
+
"pump": {
|
68
|
+
"href": "https://www.example.org/product/pump"
|
69
|
+
},
|
70
|
+
"wheels": [
|
71
|
+
{ "href": "https://www.example.org/product/bicycle/wheels/front" },
|
72
|
+
{ "href": "https://www.example.org/product/bicycle/wheels/rear" }
|
73
|
+
]
|
74
|
+
},
|
75
|
+
"bike-type": "Mountain Bike",
|
76
|
+
"BMX": false,
|
77
|
+
"derailleurs": {
|
78
|
+
"back": 7,
|
79
|
+
"front": 3
|
80
|
+
},
|
81
|
+
"name": "bicycle",
|
82
|
+
"reflectors": true,
|
83
|
+
"_embedded": {
|
84
|
+
"pump": #{pump_body},
|
85
|
+
"wheels": [#{front_wheel_body}, #{rear_wheel_body}]
|
86
|
+
}
|
87
|
+
}
|
88
|
+
EOF
|
89
|
+
end
|
90
|
+
|
91
|
+
def handlebar_body
|
92
|
+
<<~EOF
|
93
|
+
{
|
94
|
+
"_links": {
|
95
|
+
"self": "https://www.example.org/product/handlebar"
|
96
|
+
},
|
97
|
+
"material": "Carbon fiber",
|
98
|
+
"reach": "75mm",
|
99
|
+
"bend": "compact"
|
100
|
+
}
|
101
|
+
EOF
|
102
|
+
end
|
103
|
+
|
104
|
+
def pump_body
|
105
|
+
<<~EOF
|
106
|
+
{
|
107
|
+
"_links": {
|
108
|
+
"self": "https://www.example.org/product/pump"
|
109
|
+
},
|
110
|
+
"weight": "2kg",
|
111
|
+
"type": "Floor Pump",
|
112
|
+
"valve-type": "Presta"
|
113
|
+
}
|
114
|
+
EOF
|
115
|
+
end
|
116
|
+
|
117
|
+
def rear_wheel_body
|
118
|
+
<<~EOF
|
119
|
+
{
|
120
|
+
"_links": {
|
121
|
+
"self": {
|
122
|
+
"href": "https://www.example.org/product/bicycle/wheels/rear"
|
123
|
+
}
|
124
|
+
},
|
125
|
+
"position": "rear",
|
126
|
+
"lacing_pattern": "Radial"
|
127
|
+
}
|
128
|
+
EOF
|
129
|
+
end
|
130
|
+
|
131
|
+
def front_wheel_body
|
132
|
+
<<~EOF
|
133
|
+
{
|
134
|
+
"_links": {
|
135
|
+
"self": {
|
136
|
+
"href": "https://www.example.org/product/bicycle/wheels/front"
|
137
|
+
}
|
138
|
+
},
|
139
|
+
"position": "front",
|
140
|
+
"lacing_pattern": "Radial/2-Cross"
|
141
|
+
}
|
142
|
+
EOF
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
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
|
+
version: 0.4.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-
|
12
|
+
date: 2016-05-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -141,14 +141,20 @@ files:
|
|
141
141
|
- excon-hypermedia.gemspec
|
142
142
|
- lib/excon/hypermedia.rb
|
143
143
|
- lib/excon/hypermedia/ext/response.rb
|
144
|
-
- lib/excon/hypermedia/
|
144
|
+
- lib/excon/hypermedia/helpers/collection.rb
|
145
|
+
- lib/excon/hypermedia/link_object.rb
|
145
146
|
- lib/excon/hypermedia/middleware.rb
|
146
|
-
- lib/excon/hypermedia/
|
147
|
+
- lib/excon/hypermedia/resource_object.rb
|
148
|
+
- lib/excon/hypermedia/resource_object/embedded.rb
|
149
|
+
- lib/excon/hypermedia/resource_object/links.rb
|
150
|
+
- lib/excon/hypermedia/resource_object/properties.rb
|
147
151
|
- lib/excon/hypermedia/response.rb
|
148
152
|
- lib/excon/hypermedia/version.rb
|
149
|
-
- test/excon/
|
150
|
-
- test/excon/
|
151
|
-
- test/excon/
|
153
|
+
- test/excon/integration_test.rb
|
154
|
+
- test/excon/link_object_test.rb
|
155
|
+
- test/excon/links_test.rb
|
156
|
+
- test/excon/properties_test.rb
|
157
|
+
- test/excon/resource_object_test.rb
|
152
158
|
- test/test_helper.rb
|
153
159
|
homepage: https://github.com/JeanMertz/excon-hypermedia
|
154
160
|
licenses:
|
@@ -1,40 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Excon
|
4
|
-
module HyperMedia
|
5
|
-
# Link
|
6
|
-
#
|
7
|
-
# This HyperMedia::Link object encapsulates a link pointing to a resource.
|
8
|
-
#
|
9
|
-
class Link
|
10
|
-
attr_reader :name
|
11
|
-
|
12
|
-
def initialize(name:, hash:)
|
13
|
-
@hash = hash
|
14
|
-
@name = name
|
15
|
-
end
|
16
|
-
|
17
|
-
def valid?
|
18
|
-
link_data.keys.any?
|
19
|
-
end
|
20
|
-
|
21
|
-
def invalid?
|
22
|
-
!valid?
|
23
|
-
end
|
24
|
-
|
25
|
-
def uri
|
26
|
-
::Addressable::URI.parse(href)
|
27
|
-
end
|
28
|
-
|
29
|
-
def href
|
30
|
-
link_data['href']
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def link_data
|
36
|
-
@hash.dig('_links', name.to_s) || {}
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,49 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'json'
|
4
|
-
|
5
|
-
module Excon
|
6
|
-
module HyperMedia
|
7
|
-
# Resource
|
8
|
-
#
|
9
|
-
# This HyperMedia::Resource object encapsulates the returned JSON and
|
10
|
-
# makes it easy to access the links and attributes.
|
11
|
-
#
|
12
|
-
class Resource
|
13
|
-
attr_reader :data
|
14
|
-
|
15
|
-
def initialize(body)
|
16
|
-
@body = body
|
17
|
-
end
|
18
|
-
|
19
|
-
def links
|
20
|
-
data.fetch('_links', {}).keys.map { |name| link(name) }
|
21
|
-
end
|
22
|
-
|
23
|
-
def link(link_name)
|
24
|
-
Link.new(name: link_name, hash: data)
|
25
|
-
end
|
26
|
-
|
27
|
-
def attributes
|
28
|
-
attributes = data.reject do |k, _|
|
29
|
-
k == '_links'
|
30
|
-
end
|
31
|
-
|
32
|
-
Struct.new(*attributes.keys.map(&:to_sym)).new(*attributes.values)
|
33
|
-
end
|
34
|
-
|
35
|
-
def type?(name)
|
36
|
-
return :link if link(name).valid?
|
37
|
-
return :attribute if attributes.respond_to?(name.to_s)
|
38
|
-
|
39
|
-
:unknown
|
40
|
-
end
|
41
|
-
|
42
|
-
def data
|
43
|
-
@data ||= JSON.parse(@body)
|
44
|
-
rescue JSON::ParserError
|
45
|
-
{}
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|