grape-swagger 0.31.1 → 0.32.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/.rubocop_todo.yml +9 -2
- data/.travis.yml +6 -6
- data/CHANGELOG.md +20 -0
- data/Gemfile +7 -2
- data/README.md +3 -2
- data/lib/grape-swagger.rb +122 -116
- data/lib/grape-swagger/doc_methods/parse_params.rb +1 -1
- data/lib/grape-swagger/endpoint.rb +15 -15
- data/lib/grape-swagger/instance.rb +7 -0
- data/lib/grape-swagger/version.rb +1 -1
- data/spec/lib/data_type_spec.rb +18 -22
- data/spec/lib/endpoint/params_parser_spec.rb +11 -9
- data/spec/lib/move_params_spec.rb +1 -1
- data/spec/support/model_parsers/entity_parser.rb +1 -1
- data/spec/support/model_parsers/mock_parser.rb +1 -1
- data/spec/support/model_parsers/representable_parser.rb +1 -1
- data/spec/swagger_v2/api_swagger_v2_headers_spec.rb +1 -1
- data/spec/swagger_v2/default_api_spec.rb +1 -1
- data/spec/swagger_v2/endpoint_versioned_path_spec.rb +69 -26
- data/spec/swagger_v2/grape-swagger_spec.rb +4 -4
- data/spec/swagger_v2/guarded_endpoint_spec.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ea7cb947847696a10190ade08cfbe8bf19364a4b5855d932abda009c672122c4
|
|
4
|
+
data.tar.gz: 8a9c2f4a2bff62b247b795b6082d825d9403382ef56626f93ed697b4b654dc54
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 45dfe914ee2225ab36174fd182563a56aaf8cfb78f9aaccdc8a4070e47acb41e0010f31c283d6bef76819a296539457da5095191e17e181d0acf4271f743bcf0
|
|
7
|
+
data.tar.gz: 0ab65509589c8537b7f77810dd76be2fb50e092796570a333704a9b06893e8a5756988465214752df3b0a2093a731e33e10b229b7c879568e28d2f247a79dd68
|
data/.rubocop_todo.yml
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on 2018-
|
|
3
|
+
# on 2018-11-04 01:12:26 +0100 using RuboCop version 0.60.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
|
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
|
8
8
|
|
|
9
|
+
# Offense count: 1
|
|
10
|
+
# Configuration parameters: Include.
|
|
11
|
+
# Include: **/*.gemfile, **/Gemfile, **/gems.rb
|
|
12
|
+
Bundler/DuplicatedGem:
|
|
13
|
+
Exclude:
|
|
14
|
+
- 'Gemfile'
|
|
15
|
+
|
|
9
16
|
# Offense count: 1
|
|
10
17
|
# Configuration parameters: Include.
|
|
11
18
|
# Include: **/*.gemspec
|
|
@@ -35,6 +42,6 @@ Style/ClassVars:
|
|
|
35
42
|
Exclude:
|
|
36
43
|
- 'lib/grape-swagger/doc_methods.rb'
|
|
37
44
|
|
|
38
|
-
# Offense count:
|
|
45
|
+
# Offense count: 22
|
|
39
46
|
Style/Documentation:
|
|
40
47
|
Enabled: false
|
data/.travis.yml
CHANGED
|
@@ -11,22 +11,22 @@ after_success:
|
|
|
11
11
|
- bundle exec danger
|
|
12
12
|
|
|
13
13
|
rvm:
|
|
14
|
-
- 2.5
|
|
15
|
-
- 2.
|
|
14
|
+
- 2.4.5
|
|
15
|
+
- 2.5.3
|
|
16
|
+
- 2.6.0-preview2
|
|
16
17
|
env:
|
|
17
18
|
- MODEL_PARSER=grape-swagger-entity
|
|
18
19
|
- MODEL_PARSER=grape-swagger-representable
|
|
19
|
-
- GRAPE_VERSION=0.17.0
|
|
20
|
-
- GRAPE_VERSION=0.18.0
|
|
21
20
|
- GRAPE_VERSION=0.19.2
|
|
22
21
|
- GRAPE_VERSION=1.0.3
|
|
22
|
+
- GRAPE_VERSION=1.2.0
|
|
23
23
|
- GRAPE_VERSION=HEAD
|
|
24
24
|
|
|
25
25
|
matrix:
|
|
26
26
|
fast_finish: true
|
|
27
27
|
|
|
28
28
|
include:
|
|
29
|
-
- rvm: 2.3.
|
|
29
|
+
- rvm: 2.3.8
|
|
30
30
|
env:
|
|
31
31
|
- rvm: ruby-head
|
|
32
32
|
env:
|
|
@@ -34,6 +34,6 @@ matrix:
|
|
|
34
34
|
env:
|
|
35
35
|
|
|
36
36
|
allow_failures:
|
|
37
|
-
- rvm: 2.3.
|
|
37
|
+
- rvm: 2.3.8
|
|
38
38
|
- rvm: ruby-head
|
|
39
39
|
- rvm: jruby-head
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
### Next
|
|
2
|
+
|
|
3
|
+
#### Features
|
|
4
|
+
|
|
5
|
+
* Your contribution here.
|
|
6
|
+
|
|
7
|
+
#### Fixes
|
|
8
|
+
|
|
9
|
+
* Your contribution here.
|
|
10
|
+
|
|
11
|
+
### 0.32.0 (November 26, 2018)
|
|
12
|
+
|
|
13
|
+
#### Features
|
|
14
|
+
|
|
15
|
+
* [#717](https://github.com/ruby-grape/grape-swagger/pull/717): Adds support for grape >= 1.2 - [@myxoh](https://github.com/myxoh).
|
|
16
|
+
|
|
17
|
+
#### Fixes
|
|
18
|
+
|
|
19
|
+
* [#720](https://github.com/ruby-grape/grape-swagger/pull/720): Fix: corrected `termsOfService` field name in additional info - [@dblock](https://github.com/dblock).
|
|
20
|
+
|
|
1
21
|
### 0.31.1 (October 23, 2018)
|
|
2
22
|
|
|
3
23
|
#### Features
|
data/Gemfile
CHANGED
|
@@ -6,7 +6,7 @@ ruby RUBY_VERSION
|
|
|
6
6
|
|
|
7
7
|
gemspec
|
|
8
8
|
|
|
9
|
-
gem 'grape', case version = ENV['GRAPE_VERSION'] || '~> 1.
|
|
9
|
+
gem 'grape', case version = ENV['GRAPE_VERSION'] || '~> 1.2'
|
|
10
10
|
when 'HEAD'
|
|
11
11
|
{ git: 'https://github.com/ruby-grape/grape' }
|
|
12
12
|
else
|
|
@@ -26,7 +26,12 @@ group :development, :test do
|
|
|
26
26
|
gem 'rake'
|
|
27
27
|
gem 'rdoc'
|
|
28
28
|
gem 'rspec', '~> 3.0'
|
|
29
|
-
|
|
29
|
+
# TODO: change back after 2.6.0 release and updated rubocop version
|
|
30
|
+
if RUBY_VERSION == '2.6.0'
|
|
31
|
+
gem 'rubocop', git: 'https://github.com/rubocop-hq/rubocop.git', require: false
|
|
32
|
+
else
|
|
33
|
+
gem 'rubocop', '~> 0.60', require: false
|
|
34
|
+
end
|
|
30
35
|
end
|
|
31
36
|
|
|
32
37
|
group :test do
|
data/README.md
CHANGED
|
@@ -48,8 +48,9 @@ grape-swagger | swagger spec | grape | grape-entity | represen
|
|
|
48
48
|
0.10.5 | 1.2 | >= 0.10.0 ... <= 0.14.0 | < 0.5.0 | n/a |
|
|
49
49
|
0.11.0 | 1.2 | >= 0.16.2 | < 0.5.0 | n/a |
|
|
50
50
|
0.25.2 | 2.0 | >= 0.14.0 ... <= 0.18.0 | <= 0.6.0 | >= 2.4.1 |
|
|
51
|
-
0.26.0 | 2.0 | >= 0.16.2
|
|
52
|
-
0.27.0 | 2.0 | >= 0.16.2
|
|
51
|
+
0.26.0 | 2.0 | >= 0.16.2 <= 1.1.0 | <= 0.6.1 | >= 2.4.1 |
|
|
52
|
+
0.27.0 | 2.0 | >= 0.16.2 ... <= 1.1.0 | >= 0.5.0 | >= 2.4.1 |
|
|
53
|
+
0.32.0 | 2.0 | >= 0.16.2 | >= 0.5.0 | >= 2.4.1 |
|
|
53
54
|
|
|
54
55
|
|
|
55
56
|
## Swagger-Spec <a name="swagger-spec"></a>
|
data/lib/grape-swagger.rb
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require 'grape'
|
|
4
4
|
|
|
5
|
+
require 'grape-swagger/instance'
|
|
6
|
+
|
|
5
7
|
require 'grape-swagger/version'
|
|
6
8
|
require 'grape-swagger/endpoint'
|
|
7
9
|
require 'grape-swagger/errors'
|
|
@@ -18,148 +20,152 @@ module GrapeSwagger
|
|
|
18
20
|
autoload :Rake, 'grape-swagger/rake/oapi_tasks'
|
|
19
21
|
end
|
|
20
22
|
|
|
21
|
-
module
|
|
22
|
-
|
|
23
|
-
class << self
|
|
24
|
-
attr_accessor :combined_routes, :combined_namespaces, :combined_namespace_routes, :combined_namespace_identifiers
|
|
25
|
-
|
|
26
|
-
def add_swagger_documentation(options = {})
|
|
27
|
-
documentation_class = create_documentation_class
|
|
23
|
+
module SwaggerRouting
|
|
24
|
+
private
|
|
28
25
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
def combine_routes(app, doc_klass)
|
|
27
|
+
app.routes.each do |route|
|
|
28
|
+
route_path = route.path
|
|
29
|
+
route_match = route_path.split(/^.*?#{route.prefix.to_s}/).last
|
|
30
|
+
next unless route_match
|
|
33
31
|
|
|
34
|
-
|
|
32
|
+
route_match = route_match.match('\/([\w|-]*?)[\.\/\(]') || route_match.match('\/([\w|-]*)$')
|
|
33
|
+
next unless route_match
|
|
35
34
|
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
resource = route_match.captures.first
|
|
36
|
+
resource = '/' if resource.empty?
|
|
37
|
+
@target_class.combined_routes[resource] ||= []
|
|
38
|
+
next if doc_klass.hide_documentation_path && route.path.match(/#{doc_klass.mount_path}($|\/|\(\.)/)
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
@target_class.combined_routes[resource].unshift route
|
|
41
|
+
end
|
|
42
|
+
end
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
def determine_namespaced_routes(name, parent_route)
|
|
45
|
+
if parent_route.nil?
|
|
46
|
+
@target_class.combined_routes.values.flatten
|
|
47
|
+
else
|
|
48
|
+
parent_route.reject do |route|
|
|
49
|
+
!route_path_start_with?(route, name) || !route_instance_variable_equals?(route, name)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
44
53
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
54
|
+
def combine_namespace_routes(namespaces)
|
|
55
|
+
# iterate over each single namespace
|
|
56
|
+
namespaces.each_key do |name, _|
|
|
57
|
+
# get the parent route for the namespace
|
|
58
|
+
parent_route_name = extract_parent_route(name)
|
|
59
|
+
parent_route = @target_class.combined_routes[parent_route_name]
|
|
60
|
+
# fetch all routes that are within the current namespace
|
|
61
|
+
namespace_routes = determine_namespaced_routes(name, parent_route)
|
|
62
|
+
|
|
63
|
+
# default case when not explicitly specified or nested == true
|
|
64
|
+
standalone_namespaces = namespaces.reject do |_, ns|
|
|
65
|
+
!ns.options.key?(:swagger) ||
|
|
66
|
+
!ns.options[:swagger].key?(:nested) ||
|
|
67
|
+
ns.options[:swagger][:nested] != false
|
|
68
|
+
end
|
|
48
69
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
70
|
+
parent_standalone_namespaces = standalone_namespaces.select { |ns_name, _| name.start_with?(ns_name) }
|
|
71
|
+
# add only to the main route
|
|
72
|
+
# if the namespace is not within any other namespace appearing as standalone resource
|
|
73
|
+
# rubocop:disable Style/Next
|
|
74
|
+
if parent_standalone_namespaces.empty?
|
|
75
|
+
# default option, append namespace methods to parent route
|
|
76
|
+
parent_route = @target_class.combined_namespace_routes.key?(parent_route_name)
|
|
77
|
+
@target_class.combined_namespace_routes[parent_route_name] = [] unless parent_route
|
|
78
|
+
@target_class.combined_namespace_routes[parent_route_name].push(*namespace_routes)
|
|
54
79
|
end
|
|
80
|
+
# rubocop:enable Style/Next
|
|
81
|
+
end
|
|
82
|
+
end
|
|
55
83
|
|
|
56
|
-
|
|
84
|
+
def extract_parent_route(name)
|
|
85
|
+
route_name = name.match(%r{^/?([^/]*).*$})[1]
|
|
86
|
+
return route_name unless route_name.include? ':'
|
|
57
87
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
88
|
+
matches = name.match(/\/[a-z]+/)
|
|
89
|
+
matches.nil? ? route_name : matches[0].delete('/')
|
|
90
|
+
end
|
|
61
91
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
route_match = route_path.split(/^.*?#{route.prefix.to_s}/).last
|
|
66
|
-
next unless route_match
|
|
92
|
+
def route_instance_variable(route)
|
|
93
|
+
route.instance_variable_get(:@options)[:namespace]
|
|
94
|
+
end
|
|
67
95
|
|
|
68
|
-
|
|
69
|
-
|
|
96
|
+
def route_instance_variable_equals?(route, name)
|
|
97
|
+
route_instance_variable(route) == "/#{name}" ||
|
|
98
|
+
route_instance_variable(route) == "/:version/#{name}"
|
|
99
|
+
end
|
|
70
100
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
next if doc_klass.hide_documentation_path && route.path.match(/#{doc_klass.mount_path}($|\/|\(\.)/)
|
|
101
|
+
def route_path_start_with?(route, name)
|
|
102
|
+
route_prefix = route.prefix ? "/#{route.prefix}/#{name}" : "/#{name}"
|
|
103
|
+
route_versioned_prefix = route.prefix ? "/#{route.prefix}/:version/#{name}" : "/:version/#{name}"
|
|
75
104
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
105
|
+
route.path.start_with?(route_prefix, route_versioned_prefix)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
79
108
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
109
|
+
module SwaggerDocumentationAdder
|
|
110
|
+
attr_accessor :combined_namespaces, :combined_namespace_identifiers
|
|
111
|
+
attr_accessor :combined_routes, :combined_namespace_routes
|
|
112
|
+
include SwaggerRouting
|
|
83
113
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
mount_path = (endpoint.namespace_stackable(:mount_path) || []).join('/')
|
|
87
|
-
full_namespace = (mount_path + endpoint.namespace).sub(/\/{2,}/, '/').sub(/^\//, '')
|
|
88
|
-
@target_class.combined_namespaces[full_namespace] = ns if ns
|
|
114
|
+
def add_swagger_documentation(options = {})
|
|
115
|
+
documentation_class = create_documentation_class
|
|
89
116
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
117
|
+
version_for(options)
|
|
118
|
+
options = { target_class: self }.merge(options)
|
|
119
|
+
@target_class = options[:target_class]
|
|
120
|
+
auth_wrapper = options[:endpoint_auth_wrapper] || Class.new
|
|
93
121
|
|
|
94
|
-
|
|
95
|
-
if parent_route.nil?
|
|
96
|
-
@target_class.combined_routes.values.flatten
|
|
97
|
-
else
|
|
98
|
-
parent_route.reject do |route|
|
|
99
|
-
!route_path_start_with?(route, name) || !route_instance_variable_equals?(route, name)
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
end
|
|
122
|
+
use auth_wrapper if auth_wrapper.method_defined?(:before) && !middleware.flatten.include?(auth_wrapper)
|
|
103
123
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
namespaces.each_key do |name, _|
|
|
107
|
-
# get the parent route for the namespace
|
|
108
|
-
parent_route_name = extract_parent_route(name)
|
|
109
|
-
parent_route = @target_class.combined_routes[parent_route_name]
|
|
110
|
-
# fetch all routes that are within the current namespace
|
|
111
|
-
namespace_routes = determine_namespaced_routes(name, parent_route)
|
|
112
|
-
|
|
113
|
-
# default case when not explicitly specified or nested == true
|
|
114
|
-
standalone_namespaces = namespaces.reject do |_, ns|
|
|
115
|
-
!ns.options.key?(:swagger) ||
|
|
116
|
-
!ns.options[:swagger].key?(:nested) ||
|
|
117
|
-
ns.options[:swagger][:nested] != false
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
parent_standalone_namespaces = standalone_namespaces.select { |ns_name, _| name.start_with?(ns_name) }
|
|
121
|
-
# add only to the main route
|
|
122
|
-
# if the namespace is not within any other namespace appearing as standalone resource
|
|
123
|
-
# rubocop:disable Style/Next
|
|
124
|
-
if parent_standalone_namespaces.empty?
|
|
125
|
-
# default option, append namespace methods to parent route
|
|
126
|
-
parent_route = @target_class.combined_namespace_routes.key?(parent_route_name)
|
|
127
|
-
@target_class.combined_namespace_routes[parent_route_name] = [] unless parent_route
|
|
128
|
-
@target_class.combined_namespace_routes[parent_route_name].push(*namespace_routes)
|
|
129
|
-
end
|
|
130
|
-
# rubocop:enable Style/Next
|
|
131
|
-
end
|
|
132
|
-
end
|
|
124
|
+
documentation_class.setup(options)
|
|
125
|
+
mount(documentation_class)
|
|
133
126
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
return route_name unless route_name.include? ':'
|
|
127
|
+
@target_class.combined_routes = {}
|
|
128
|
+
combine_routes(@target_class, documentation_class)
|
|
137
129
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
end
|
|
130
|
+
@target_class.combined_namespaces = {}
|
|
131
|
+
combine_namespaces(@target_class)
|
|
141
132
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
133
|
+
@target_class.combined_namespace_routes = {}
|
|
134
|
+
@target_class.combined_namespace_identifiers = {}
|
|
135
|
+
combine_namespace_routes(@target_class.combined_namespaces)
|
|
145
136
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
137
|
+
exclusive_route_keys = @target_class.combined_routes.keys - @target_class.combined_namespaces.keys
|
|
138
|
+
exclusive_route_keys.each do |key|
|
|
139
|
+
@target_class.combined_namespace_routes[key] = @target_class.combined_routes[key]
|
|
140
|
+
end
|
|
141
|
+
documentation_class
|
|
142
|
+
end
|
|
150
143
|
|
|
151
|
-
|
|
152
|
-
route_prefix = route.prefix ? "/#{route.prefix}/#{name}" : "/#{name}"
|
|
153
|
-
route_versioned_prefix = route.prefix ? "/#{route.prefix}/:version/#{name}" : "/:version/#{name}"
|
|
144
|
+
private
|
|
154
145
|
|
|
155
|
-
|
|
156
|
-
|
|
146
|
+
def version_for(options)
|
|
147
|
+
options[:version] = version if version
|
|
148
|
+
end
|
|
157
149
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
150
|
+
def combine_namespaces(app)
|
|
151
|
+
app.endpoints.each do |endpoint|
|
|
152
|
+
ns = endpoint.namespace_stackable(:namespace).last
|
|
153
|
+
|
|
154
|
+
# use the full namespace here (not the latest level only)
|
|
155
|
+
# and strip leading slash
|
|
156
|
+
mount_path = (endpoint.namespace_stackable(:mount_path) || []).join('/')
|
|
157
|
+
full_namespace = (mount_path + endpoint.namespace).sub(/\/{2,}/, '/').sub(/^\//, '')
|
|
158
|
+
@target_class.combined_namespaces[full_namespace] = ns if ns
|
|
159
|
+
|
|
160
|
+
combine_namespaces(endpoint.options[:app]) if endpoint.options[:app]
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def create_documentation_class
|
|
165
|
+
Class.new(GrapeInstance) do
|
|
166
|
+
extend GrapeSwagger::DocMethods
|
|
163
167
|
end
|
|
164
168
|
end
|
|
165
169
|
end
|
|
170
|
+
|
|
171
|
+
GrapeInstance.extend(SwaggerDocumentationAdder)
|
|
@@ -25,15 +25,15 @@ module Grape
|
|
|
25
25
|
# required keys for SwaggerObject
|
|
26
26
|
def swagger_object(target_class, request, options)
|
|
27
27
|
object = {
|
|
28
|
-
info:
|
|
29
|
-
swagger:
|
|
30
|
-
produces:
|
|
31
|
-
authorizations:
|
|
28
|
+
info: info_object(options[:info].merge(version: options[:doc_version])),
|
|
29
|
+
swagger: '2.0',
|
|
30
|
+
produces: content_types_for(target_class),
|
|
31
|
+
authorizations: options[:authorizations],
|
|
32
32
|
securityDefinitions: options[:security_definitions],
|
|
33
|
-
security:
|
|
34
|
-
host:
|
|
35
|
-
basePath:
|
|
36
|
-
schemes:
|
|
33
|
+
security: options[:security],
|
|
34
|
+
host: GrapeSwagger::DocMethods::OptionalObject.build(:host, options, request),
|
|
35
|
+
basePath: GrapeSwagger::DocMethods::OptionalObject.build(:base_path, options, request),
|
|
36
|
+
schemes: options[:schemes].is_a?(String) ? [options[:schemes]] : options[:schemes]
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
GrapeSwagger::DocMethods::Extensions.add_extensions_to_root(options, object)
|
|
@@ -43,12 +43,12 @@ module Grape
|
|
|
43
43
|
# building info object
|
|
44
44
|
def info_object(infos)
|
|
45
45
|
result = {
|
|
46
|
-
title:
|
|
47
|
-
description:
|
|
48
|
-
|
|
49
|
-
contact:
|
|
50
|
-
license:
|
|
51
|
-
version:
|
|
46
|
+
title: infos[:title] || 'API title',
|
|
47
|
+
description: infos[:description],
|
|
48
|
+
termsOfService: infos[:terms_of_service_url],
|
|
49
|
+
contact: contact_object(infos),
|
|
50
|
+
license: license_object(infos),
|
|
51
|
+
version: infos[:version]
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
GrapeSwagger::DocMethods::Extensions.add_extensions_to_info(infos, result)
|
|
@@ -61,7 +61,7 @@ module Grape
|
|
|
61
61
|
def license_object(infos)
|
|
62
62
|
{
|
|
63
63
|
name: infos.delete(:license),
|
|
64
|
-
url:
|
|
64
|
+
url: infos.delete(:license_url)
|
|
65
65
|
}.delete_if { |_, value| value.blank? }
|
|
66
66
|
end
|
|
67
67
|
|
data/spec/lib/data_type_spec.rb
CHANGED
|
@@ -3,15 +3,6 @@
|
|
|
3
3
|
require 'spec_helper'
|
|
4
4
|
|
|
5
5
|
describe GrapeSwagger::DocMethods::DataType do
|
|
6
|
-
before do
|
|
7
|
-
stub_const 'MyEntity', Class.new
|
|
8
|
-
MyEntity.class_eval do
|
|
9
|
-
def self.entity_name
|
|
10
|
-
'MyInteger'
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
6
|
subject { described_class.call(value) }
|
|
16
7
|
|
|
17
8
|
describe 'standards' do
|
|
@@ -26,78 +17,83 @@ describe GrapeSwagger::DocMethods::DataType do
|
|
|
26
17
|
describe 'Hash' do
|
|
27
18
|
let(:value) { { type: Hash } }
|
|
28
19
|
|
|
29
|
-
it {
|
|
20
|
+
it { is_expected.to eq 'object' }
|
|
30
21
|
end
|
|
31
22
|
|
|
32
23
|
describe 'Multi types in a string' do
|
|
33
24
|
let(:value) { { type: '[String, Integer]' } }
|
|
34
25
|
|
|
35
|
-
it {
|
|
26
|
+
it { is_expected.to eq 'string' }
|
|
36
27
|
end
|
|
37
28
|
|
|
38
29
|
describe 'Multi types in a string stating with A' do
|
|
39
30
|
let(:value) { { type: '[Apple, Orange]' } }
|
|
40
31
|
|
|
41
|
-
it {
|
|
32
|
+
it { is_expected.to eq 'Apple' }
|
|
42
33
|
end
|
|
43
34
|
|
|
44
35
|
describe 'Multi types in array' do
|
|
45
36
|
let(:value) { { type: [String, Integer] } }
|
|
46
37
|
|
|
47
|
-
it {
|
|
38
|
+
it { is_expected.to eq 'string' }
|
|
48
39
|
end
|
|
49
40
|
|
|
50
41
|
describe 'Types in array with entity_name' do
|
|
42
|
+
before do
|
|
43
|
+
stub_const 'MyEntity', Class.new
|
|
44
|
+
allow(MyEntity).to receive(:entity_name).and_return 'MyInteger'
|
|
45
|
+
end
|
|
46
|
+
|
|
51
47
|
let(:value) { { type: '[MyEntity]' } }
|
|
52
48
|
|
|
53
|
-
it {
|
|
49
|
+
it { is_expected.to eq 'MyInteger' }
|
|
54
50
|
end
|
|
55
51
|
|
|
56
52
|
describe 'Rack::Multipart::UploadedFile' do
|
|
57
53
|
let(:value) { { type: Rack::Multipart::UploadedFile } }
|
|
58
54
|
|
|
59
|
-
it {
|
|
55
|
+
it { is_expected.to eq 'file' }
|
|
60
56
|
end
|
|
61
57
|
|
|
62
58
|
describe 'Virtus::Attribute::Boolean' do
|
|
63
59
|
let(:value) { { type: Virtus::Attribute::Boolean } }
|
|
64
60
|
|
|
65
|
-
it {
|
|
61
|
+
it { is_expected.to eq 'boolean' }
|
|
66
62
|
end
|
|
67
63
|
|
|
68
64
|
describe 'BigDecimal' do
|
|
69
65
|
let(:value) { { type: BigDecimal } }
|
|
70
66
|
|
|
71
|
-
it {
|
|
67
|
+
it { is_expected.to eq 'double' }
|
|
72
68
|
end
|
|
73
69
|
|
|
74
70
|
describe 'DateTime' do
|
|
75
71
|
let(:value) { { type: DateTime } }
|
|
76
72
|
|
|
77
|
-
it {
|
|
73
|
+
it { is_expected.to eq 'dateTime' }
|
|
78
74
|
end
|
|
79
75
|
|
|
80
76
|
describe 'Numeric' do
|
|
81
77
|
let(:value) { { type: Numeric } }
|
|
82
78
|
|
|
83
|
-
it {
|
|
79
|
+
it { is_expected.to eq 'long' }
|
|
84
80
|
end
|
|
85
81
|
|
|
86
82
|
describe 'Symbol' do
|
|
87
83
|
let(:value) { { type: Symbol } }
|
|
88
84
|
|
|
89
|
-
it {
|
|
85
|
+
it { is_expected.to eq 'string' }
|
|
90
86
|
end
|
|
91
87
|
|
|
92
88
|
describe '[String]' do
|
|
93
89
|
let(:value) { { type: '[String]' } }
|
|
94
90
|
|
|
95
|
-
it {
|
|
91
|
+
it { is_expected.to eq('string') }
|
|
96
92
|
end
|
|
97
93
|
|
|
98
94
|
describe '[Integer]' do
|
|
99
95
|
let(:value) { { type: '[Integer]' } }
|
|
100
96
|
|
|
101
|
-
it {
|
|
97
|
+
it { is_expected.to eq('integer') }
|
|
102
98
|
end
|
|
103
99
|
end
|
|
@@ -9,18 +9,20 @@ describe GrapeSwagger::Endpoint::ParamsParser do
|
|
|
9
9
|
let(:parser) { described_class.new(params, settings) }
|
|
10
10
|
|
|
11
11
|
describe '#parse_request_params' do
|
|
12
|
+
subject(:parse_request_params) { parser.parse_request_params }
|
|
13
|
+
|
|
12
14
|
context 'when param is of array type' do
|
|
13
15
|
let(:params) { [['param_1', { type: 'Array[String]' }]] }
|
|
14
16
|
|
|
15
17
|
it 'adds is_array option' do
|
|
16
|
-
expect(
|
|
18
|
+
expect(parse_request_params['param_1']).to eq(type: 'Array[String]', is_array: true)
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
context 'and array_use_braces setting set to true' do
|
|
20
22
|
let(:settings) { { array_use_braces: true } }
|
|
21
23
|
|
|
22
24
|
it 'adds braces to the param key' do
|
|
23
|
-
expect(
|
|
25
|
+
expect(parse_request_params.keys.first).to eq 'param_1[]'
|
|
24
26
|
end
|
|
25
27
|
end
|
|
26
28
|
end
|
|
@@ -29,7 +31,7 @@ describe GrapeSwagger::Endpoint::ParamsParser do
|
|
|
29
31
|
let(:params) { [['param_1', { type: 'String' }]] }
|
|
30
32
|
|
|
31
33
|
it 'does not change options' do
|
|
32
|
-
expect(
|
|
34
|
+
expect(parse_request_params['param_1']).to eq(type: 'String')
|
|
33
35
|
end
|
|
34
36
|
|
|
35
37
|
context 'and array_use_braces setting set to true' do
|
|
@@ -45,18 +47,18 @@ describe GrapeSwagger::Endpoint::ParamsParser do
|
|
|
45
47
|
let(:params) { [['param_1', { type: 'Array' }], ['param_1[param_2]', { type: 'String' }]] }
|
|
46
48
|
|
|
47
49
|
it 'skips root parameter' do
|
|
48
|
-
|
|
50
|
+
is_expected.not_to have_key 'param_1'
|
|
49
51
|
end
|
|
50
52
|
|
|
51
53
|
it 'adds is_array option to the nested param' do
|
|
52
|
-
expect(
|
|
54
|
+
expect(parse_request_params['param_1[param_2]']).to eq(type: 'String', is_array: true)
|
|
53
55
|
end
|
|
54
56
|
|
|
55
57
|
context 'and array_use_braces setting set to true' do
|
|
56
58
|
let(:settings) { { array_use_braces: true } }
|
|
57
59
|
|
|
58
60
|
it 'adds braces to the param key' do
|
|
59
|
-
expect(
|
|
61
|
+
expect(parse_request_params.keys.first).to eq 'param_1[][param_2]'
|
|
60
62
|
end
|
|
61
63
|
end
|
|
62
64
|
end
|
|
@@ -65,18 +67,18 @@ describe GrapeSwagger::Endpoint::ParamsParser do
|
|
|
65
67
|
let(:params) { [['param_1', { type: 'Hash' }], ['param_1[param_2]', { type: 'String' }]] }
|
|
66
68
|
|
|
67
69
|
it 'skips root parameter' do
|
|
68
|
-
|
|
70
|
+
is_expected.not_to have_key 'param_1'
|
|
69
71
|
end
|
|
70
72
|
|
|
71
73
|
it 'does not change options to the nested param' do
|
|
72
|
-
expect(
|
|
74
|
+
expect(parse_request_params['param_1[param_2]']).to eq(type: 'String')
|
|
73
75
|
end
|
|
74
76
|
|
|
75
77
|
context 'and array_use_braces setting set to true' do
|
|
76
78
|
let(:settings) { { array_use_braces: true } }
|
|
77
79
|
|
|
78
80
|
it 'does not add braces to the param key' do
|
|
79
|
-
expect(
|
|
81
|
+
expect(parse_request_params.keys.first).to eq 'param_1[param_2]'
|
|
80
82
|
end
|
|
81
83
|
end
|
|
82
84
|
end
|
|
@@ -189,7 +189,7 @@ RSpec.shared_context 'entity swagger example' do
|
|
|
189
189
|
'info' => {
|
|
190
190
|
'title' => 'The API title to be displayed on the API homepage.',
|
|
191
191
|
'description' => 'A description of the API.',
|
|
192
|
-
'
|
|
192
|
+
'termsOfService' => 'www.The-URL-of-the-terms-and-service.com',
|
|
193
193
|
'contact' => { 'name' => 'Contact name', 'email' => 'Contact@email.com', 'url' => 'Contact URL' },
|
|
194
194
|
'license' => { 'name' => 'The name of the license.', 'url' => 'www.The-URL-of-the-license.org' },
|
|
195
195
|
'version' => '0.0.1'
|
|
@@ -181,7 +181,7 @@ RSpec.shared_context 'mock swagger example' do
|
|
|
181
181
|
'info' => {
|
|
182
182
|
'title' => 'The API title to be displayed on the API homepage.',
|
|
183
183
|
'description' => 'A description of the API.',
|
|
184
|
-
'
|
|
184
|
+
'termsOfService' => 'www.The-URL-of-the-terms-and-service.com',
|
|
185
185
|
'contact' => { 'name' => 'Contact name', 'email' => 'Contact@email.com', 'url' => 'Contact URL' },
|
|
186
186
|
'license' => { 'name' => 'The name of the license.', 'url' => 'www.The-URL-of-the-license.org' },
|
|
187
187
|
'version' => '0.0.1'
|
|
@@ -261,7 +261,7 @@ RSpec.shared_context 'representable swagger example' do
|
|
|
261
261
|
'info' => {
|
|
262
262
|
'title' => 'The API title to be displayed on the API homepage.',
|
|
263
263
|
'description' => 'A description of the API.',
|
|
264
|
-
'
|
|
264
|
+
'termsOfService' => 'www.The-URL-of-the-terms-and-service.com',
|
|
265
265
|
'contact' => { 'name' => 'Contact name', 'email' => 'Contact@email.com', 'url' => 'Contact URL' },
|
|
266
266
|
'license' => { 'name' => 'The name of the license.', 'url' => 'www.The-URL-of-the-license.org' },
|
|
267
267
|
'version' => '0.0.1'
|
|
@@ -12,7 +12,7 @@ describe 'headers' do
|
|
|
12
12
|
|
|
13
13
|
desc 'This returns something',
|
|
14
14
|
failure: [{ code: 400, model: Entities::ApiError }],
|
|
15
|
-
headers:
|
|
15
|
+
headers: {
|
|
16
16
|
'X-Rate-Limit-Limit' => {
|
|
17
17
|
'description' => 'The number of allowed requests in the current period',
|
|
18
18
|
'type' => 'integer'
|
|
@@ -128,7 +128,7 @@ describe 'Default API' do
|
|
|
128
128
|
end
|
|
129
129
|
|
|
130
130
|
it 'documents the terms of service url' do
|
|
131
|
-
expect(subject['
|
|
131
|
+
expect(subject['termsOfService']).to eql('http://terms.com')
|
|
132
132
|
end
|
|
133
133
|
|
|
134
134
|
it 'documents the contact email' do
|
|
@@ -3,52 +3,95 @@
|
|
|
3
3
|
require 'spec_helper'
|
|
4
4
|
|
|
5
5
|
describe 'Grape::Endpoint#path_and_definitions' do
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
context 'when mounting an API once' do
|
|
7
|
+
let(:item) do
|
|
8
|
+
Class.new(Grape::API) do
|
|
9
|
+
version 'v1', using: :path
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
resource :item do
|
|
12
|
+
get '/'
|
|
13
|
+
end
|
|
12
14
|
end
|
|
13
15
|
end
|
|
14
|
-
end
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
let(:api) do
|
|
18
|
+
item_api = item
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
Class.new(Grape::API) do
|
|
21
|
+
mount item_api
|
|
22
|
+
add_swagger_documentation add_version: true
|
|
23
|
+
end
|
|
22
24
|
end
|
|
23
|
-
end
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
let(:options) { { add_version: true } }
|
|
27
|
+
let(:target_routes) { api.combined_namespace_routes }
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
subject { api.endpoints[0].path_and_definition_objects(target_routes, options) }
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
it 'is returning a versioned path' do
|
|
32
|
+
expect(subject[0].keys[0]).to eq '/v1/item'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'tags the endpoint with the resource name' do
|
|
36
|
+
expect(subject.first['/v1/item'][:get][:tags]).to eq ['item']
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context 'when custom tags are specified' do
|
|
40
|
+
let(:item) do
|
|
41
|
+
Class.new(Grape::API) do
|
|
42
|
+
version 'v1', using: :path
|
|
43
|
+
|
|
44
|
+
resource :item do
|
|
45
|
+
desc 'Item description', tags: ['special-item']
|
|
46
|
+
get '/'
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
33
50
|
|
|
34
|
-
|
|
35
|
-
|
|
51
|
+
it 'tags the endpoint with the custom tags' do
|
|
52
|
+
expect(subject.first['/v1/item'][:get][:tags]).to eq ['special-item']
|
|
53
|
+
end
|
|
54
|
+
end
|
|
36
55
|
end
|
|
37
56
|
|
|
38
|
-
context 'when
|
|
57
|
+
context 'when mounting an API more than once', if: GrapeVersion.satisfy?('>= 1.2.0') do
|
|
39
58
|
let(:item) do
|
|
40
59
|
Class.new(Grape::API) do
|
|
41
|
-
version 'v1', using: :path
|
|
42
|
-
|
|
43
60
|
resource :item do
|
|
44
|
-
desc 'Item description', tags: ['
|
|
61
|
+
desc 'Item description', tags: [configuration[:tag] || 'item']
|
|
45
62
|
get '/'
|
|
46
63
|
end
|
|
47
64
|
end
|
|
48
65
|
end
|
|
49
66
|
|
|
50
|
-
|
|
51
|
-
|
|
67
|
+
let(:api) do
|
|
68
|
+
item_api = item
|
|
69
|
+
Class.new(Grape::API) do
|
|
70
|
+
version 'v1', using: :path do
|
|
71
|
+
mount item_api
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
version 'v2', using: :path do
|
|
75
|
+
mount item_api, with: { tag: 'special-item' }
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
add_swagger_documentation add_version: true
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
let(:options) { { add_version: true } }
|
|
83
|
+
let(:target_routes) { api.combined_namespace_routes }
|
|
84
|
+
|
|
85
|
+
subject { api.endpoints[0].path_and_definition_objects(target_routes, options) }
|
|
86
|
+
|
|
87
|
+
it 'retrieves both apis respecting their configured tags' do
|
|
88
|
+
expect(subject.first['/v1/item'][:get][:tags]).to eq ['item']
|
|
89
|
+
expect(subject.first['/v2/item'][:get][:tags]).to eq ['special-item']
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'retrieves both apis with descriptions' do
|
|
93
|
+
expect(subject.first['/v1/item'][:get][:description]).to eq 'Item description'
|
|
94
|
+
expect(subject.first['/v2/item'][:get][:description]).to eq 'Item description'
|
|
52
95
|
end
|
|
53
96
|
end
|
|
54
97
|
end
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
require 'spec_helper'
|
|
4
4
|
|
|
5
|
-
describe
|
|
5
|
+
describe GrapeInstance do
|
|
6
6
|
it 'added combined-routes' do
|
|
7
|
-
expect(
|
|
7
|
+
expect(described_class).to respond_to :combined_routes
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
it 'added add_swagger_documentation' do
|
|
11
|
-
expect(
|
|
11
|
+
expect(described_class).to respond_to :add_swagger_documentation
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
it 'added combined-namespaces' do
|
|
15
|
-
expect(
|
|
15
|
+
expect(described_class).to respond_to :combined_namespaces
|
|
16
16
|
end
|
|
17
17
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: grape-swagger
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.32.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tim Vandecasteele
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2018-
|
|
11
|
+
date: 2018-11-26 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: grape
|
|
@@ -72,6 +72,7 @@ files:
|
|
|
72
72
|
- lib/grape-swagger/endpoint.rb
|
|
73
73
|
- lib/grape-swagger/endpoint/params_parser.rb
|
|
74
74
|
- lib/grape-swagger/errors.rb
|
|
75
|
+
- lib/grape-swagger/instance.rb
|
|
75
76
|
- lib/grape-swagger/model_parsers.rb
|
|
76
77
|
- lib/grape-swagger/rake/oapi_tasks.rb
|
|
77
78
|
- lib/grape-swagger/version.rb
|
|
@@ -189,7 +190,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
189
190
|
version: '0'
|
|
190
191
|
requirements: []
|
|
191
192
|
rubyforge_project:
|
|
192
|
-
rubygems_version: 2.7.
|
|
193
|
+
rubygems_version: 2.7.8
|
|
193
194
|
signing_key:
|
|
194
195
|
specification_version: 4
|
|
195
196
|
summary: Add auto generated documentation to your Grape API that can be displayed
|