api-extensions 0.0.1 → 0.0.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 +8 -8
- data/README.md +33 -0
- data/features/expand.feature +42 -0
- data/features/step_definitions/common_steps.rb +15 -0
- data/features/step_definitions/expand_steps.rb +31 -0
- data/features/step_definitions/fields_steps.rb +3 -3
- data/lib/api/extensions/expand.rb +61 -0
- data/lib/api/extensions/version.rb +1 -1
- data/lib/api/extensions.rb +1 -0
- metadata +6 -1
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
N2U3NWJjOWY4MWM1OGY2ZDZjMDgwNWJmY2ZkODY2NTU3ZTYzZjQyZg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
OTJiZmZmOTI2NmU1ZTgyNjg5ODk4OGIxMzc1YzVkZDM2ZWQyY2I4Yw==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZDY3NGM1MmU0MDRkNjQyM2FkY2FjNTc2MmI1YTA0OGJkOTM0MWIzZTc0MThm
|
10
|
+
YmM1YTAxMWUxZTdlNjE1OWJjNDFkNmJjZjczOGQ5ZDQyOWZlYzkxMWZkM2Rj
|
11
|
+
ODU1ZWFlMTRmZjY0YzllYTIxYTFlYTFlMjAwMTUxYWIzMDc0MWQ=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YWY5MWI3MTAwZjNiYWU2NmM0ODRkZmRmZjMxMmQzYjExNmY0ZGUyNjY0MGI5
|
14
|
+
ZDdhYzUyYThmODA2ZmJjNThkOTI4MTRjYTVjNWQ2Yzk5ZmZlZWUyMjI3OTI1
|
15
|
+
NDhjOGRiNjJiYmQ2M2QwNTY1NTQ4NGY1MTk5NzcwYzY0NGI5M2Q=
|
data/README.md
CHANGED
@@ -23,6 +23,32 @@ Or install it yourself as:
|
|
23
23
|
|
24
24
|
## Usage
|
25
25
|
|
26
|
+
### `expand` extension
|
27
|
+
|
28
|
+
The behavior of this extension is best described at
|
29
|
+
[the api-doc repo](https://github.com/ncuesta/api-doc/blob/master/README.en.md#links-expansion).
|
30
|
+
|
31
|
+
By including the `Api::Extensions::Expand` module in any class, you will get a `process_expand`
|
32
|
+
method that will handle the expansion of linked resources - as described in the linked document.
|
33
|
+
|
34
|
+
Please note that this extension **requires that the including class responds to a `get` method**.
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
require 'api/extensions/expand'
|
38
|
+
|
39
|
+
class MyApiHandler
|
40
|
+
|
41
|
+
def initialize
|
42
|
+
include Api::Extensions::Expand
|
43
|
+
end
|
44
|
+
|
45
|
+
def handle(request)
|
46
|
+
response = fiddle_with request
|
47
|
+
process_expand request[:expand], response
|
48
|
+
end
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
26
52
|
### `fields` extension
|
27
53
|
|
28
54
|
The behavior of this extension is best described at
|
@@ -44,6 +70,13 @@ class MyApiHandler
|
|
44
70
|
end
|
45
71
|
```
|
46
72
|
|
73
|
+
## Running tests
|
74
|
+
|
75
|
+
The test suite uses Cucumber, and can be run through `rake`:
|
76
|
+
|
77
|
+
```bash
|
78
|
+
$ rake features
|
79
|
+
```
|
47
80
|
|
48
81
|
## Contributing
|
49
82
|
|
@@ -0,0 +1,42 @@
|
|
1
|
+
Feature: Expand functional extension
|
2
|
+
In order to reduce the amount of requests sent to the API
|
3
|
+
As a client application
|
4
|
+
I want to be able to specify which related links I need expanded
|
5
|
+
|
6
|
+
Scenario Outline: Invalid expand values are ignored
|
7
|
+
Given I get a request for resource "/articles/1.json"
|
8
|
+
And I get the expand parameter "<value>"
|
9
|
+
When I process the expand parameter
|
10
|
+
Then the resulting response should be the same as the original one
|
11
|
+
|
12
|
+
Examples:
|
13
|
+
| value |
|
14
|
+
| |
|
15
|
+
| , |
|
16
|
+
| ,, |
|
17
|
+
| non-existing-key |
|
18
|
+
| non,existing,key |
|
19
|
+
| non(existing) |
|
20
|
+
|
21
|
+
|
22
|
+
Scenario Outline: Links expansion for singular documents
|
23
|
+
Given I get a request for resource "/articles/1.json"
|
24
|
+
And I get the expand parameter "<value>"
|
25
|
+
When I process the expand parameter
|
26
|
+
Then the resulting response should include the original response
|
27
|
+
And the resulting response should also contain "<expanded_links>" as new attributes
|
28
|
+
|
29
|
+
Examples:
|
30
|
+
| value | expanded_links |
|
31
|
+
| title | title |
|
32
|
+
| title,name | title,name |
|
33
|
+
| title,name, | title,name |
|
34
|
+
| title,name,non_existent_field | title,name |
|
35
|
+
|
36
|
+
|
37
|
+
Scenario: Links expansion for collective documents
|
38
|
+
Given I get a request for resource "/articles.json"
|
39
|
+
And I get the expand parameter "entries(self)"
|
40
|
+
When I process the expand parameter
|
41
|
+
Then the resulting response should include the original response
|
42
|
+
And the resulting response should have the entries expanded
|
@@ -12,6 +12,21 @@ def resources
|
|
12
12
|
'self' => { 'href' => '/link/to/self' },
|
13
13
|
'other' => { 'href' => '/link/to/other' }
|
14
14
|
}
|
15
|
+
},
|
16
|
+
'/articles.json' => {
|
17
|
+
'entries' => [
|
18
|
+
{
|
19
|
+
'links' => {
|
20
|
+
'self' => { 'href' => '/articles/1.json' }
|
21
|
+
}
|
22
|
+
}
|
23
|
+
],
|
24
|
+
'total' => 1,
|
25
|
+
'limit' => 10,
|
26
|
+
'offset' => 0,
|
27
|
+
'links' => {
|
28
|
+
'self' => { 'href' => '/link/to/self' }
|
29
|
+
}
|
15
30
|
}
|
16
31
|
}
|
17
32
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'api/extensions/expand'
|
2
|
+
|
3
|
+
Before do
|
4
|
+
@expand_processor = Object.new
|
5
|
+
class << @expand_processor
|
6
|
+
def get url
|
7
|
+
end
|
8
|
+
|
9
|
+
include(Api::Extensions::Expand)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
Given(/^I get the expand parameter "(.*)"$/) do |value|
|
14
|
+
@expand = value
|
15
|
+
end
|
16
|
+
|
17
|
+
When(/^I process the expand parameter$/) do
|
18
|
+
@result = @expand_processor.process_expand @expand, @response
|
19
|
+
end
|
20
|
+
|
21
|
+
Then(/^the resulting response should include the original response$/) do
|
22
|
+
pending # express the regexp above with the code you wish you had
|
23
|
+
end
|
24
|
+
|
25
|
+
Then(/^the resulting response should also contain "(.*?)" as new attributes$/) do |arg1|
|
26
|
+
pending # express the regexp above with the code you wish you had
|
27
|
+
end
|
28
|
+
|
29
|
+
Then(/^the resulting response should have the entries expanded$/) do
|
30
|
+
pending # express the regexp above with the code you wish you had
|
31
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'api/extensions/fields'
|
2
2
|
|
3
3
|
Before do
|
4
|
-
@
|
5
|
-
class << @
|
4
|
+
@fields_processor = Object.new
|
5
|
+
class << @fields_processor
|
6
6
|
include(Api::Extensions::Fields)
|
7
7
|
end
|
8
8
|
end
|
@@ -17,7 +17,7 @@ Given /^I get the fields parameter "(.*)"$/ do |value|
|
|
17
17
|
end
|
18
18
|
|
19
19
|
When /^I process the fields parameter$/ do
|
20
|
-
@result = @
|
20
|
+
@result = @fields_processor.process_fields @fields, @response, @request_path
|
21
21
|
end
|
22
22
|
|
23
23
|
Then /^the resulting response should include the required fields$/ do
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#
|
2
|
+
# Expand extension
|
3
|
+
#
|
4
|
+
# https://github.com/ncuesta/api-doc/blob/master/README.en.md#links-expansion
|
5
|
+
#
|
6
|
+
module Api
|
7
|
+
module Extensions
|
8
|
+
module Expand
|
9
|
+
# Check requirements on inclusion
|
10
|
+
def self.included(base)
|
11
|
+
raise ::Exception.new('Base class must implement a :get method to include the ExpandProcessor module') unless base.method_defined?(:get)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Process the expand functional extension
|
15
|
+
def process_expand(keys, scope)
|
16
|
+
keys.split(',').each do |key|
|
17
|
+
entries_parts = key.match(/entries\((.*)\)$/)
|
18
|
+
|
19
|
+
if entries_parts && scope['entries']
|
20
|
+
# (2) Collective key: expand=entries(self)
|
21
|
+
scope['entries'].collect! { |entry| process_expand entries_parts[1], entry }
|
22
|
+
else
|
23
|
+
recursive = key.match(/([^\(]+)\((.*)\)$/)
|
24
|
+
|
25
|
+
if recursive
|
26
|
+
# (1) Recursive key: expand=section(parent)
|
27
|
+
local_key, sub_key = recursive[1, 2]
|
28
|
+
# Expand the local key
|
29
|
+
scope = expand scope, local_key
|
30
|
+
# Recursively expand the remaining keys - if possible
|
31
|
+
new_scope = local_key == 'self' ? scope : scope[local_key]
|
32
|
+
process_expand(sub_key, new_scope) if new_scope
|
33
|
+
else
|
34
|
+
# (0) Simple key: expand=section
|
35
|
+
scope = expand scope, key
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
scope
|
41
|
+
end
|
42
|
+
|
43
|
+
# Actually expand a link
|
44
|
+
def expand(resource, link)
|
45
|
+
if resource['links'].include?(link)
|
46
|
+
sub_resource_uri = resource['links'][link]['href']
|
47
|
+
sub_resource = get sub_resource_uri
|
48
|
+
|
49
|
+
# 'self' links replace the original resource
|
50
|
+
if link == 'self'
|
51
|
+
resource = sub_resource
|
52
|
+
else
|
53
|
+
resource[link] = sub_resource
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
resource
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/api/extensions.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: api-extensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nahuel Cuesta Luengo
|
@@ -81,10 +81,13 @@ files:
|
|
81
81
|
- Rakefile
|
82
82
|
- api-extensions.gemspec
|
83
83
|
- cucumber.yml
|
84
|
+
- features/expand.feature
|
84
85
|
- features/fields.feature
|
85
86
|
- features/step_definitions/common_steps.rb
|
87
|
+
- features/step_definitions/expand_steps.rb
|
86
88
|
- features/step_definitions/fields_steps.rb
|
87
89
|
- lib/api/extensions.rb
|
90
|
+
- lib/api/extensions/expand.rb
|
88
91
|
- lib/api/extensions/fields.rb
|
89
92
|
- lib/api/extensions/version.rb
|
90
93
|
homepage: https://github.com/ncuesta/api-extensions
|
@@ -112,6 +115,8 @@ signing_key:
|
|
112
115
|
specification_version: 4
|
113
116
|
summary: A collection of extensions for Hypermedia-driven APIs
|
114
117
|
test_files:
|
118
|
+
- features/expand.feature
|
115
119
|
- features/fields.feature
|
116
120
|
- features/step_definitions/common_steps.rb
|
121
|
+
- features/step_definitions/expand_steps.rb
|
117
122
|
- features/step_definitions/fields_steps.rb
|