api-extensions 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|