grape-swagger 0.21.0 → 0.22.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.yml +1 -0
- data/.rubocop_todo.yml +1 -1
- data/CHANGELOG.md +24 -2
- data/Gemfile +5 -0
- data/README.md +105 -3
- data/example/api/endpoints.rb +16 -16
- data/lib/grape-swagger.rb +0 -1
- data/lib/grape-swagger/doc_methods.rb +1 -0
- data/lib/grape-swagger/doc_methods/data_type.rb +15 -3
- data/lib/grape-swagger/doc_methods/extensions.rb +16 -12
- data/lib/grape-swagger/doc_methods/move_params.rb +139 -94
- data/lib/grape-swagger/doc_methods/parse_params.rb +9 -7
- data/lib/grape-swagger/endpoint.rb +36 -17
- data/lib/grape-swagger/version.rb +1 -1
- data/spec/lib/data_type_spec.rb +24 -0
- data/spec/lib/endpoint_spec.rb +13 -0
- data/spec/lib/move_params_spec.rb +124 -116
- data/spec/support/model_parsers/entity_parser.rb +8 -2
- data/spec/support/model_parsers/mock_parser.rb +10 -0
- data/spec/support/model_parsers/representable_parser.rb +7 -0
- data/spec/support/the_paths_definitions.rb +1 -2
- data/spec/swagger_v2/api_swagger_v2_definitions-models_spec.rb +2 -1
- data/spec/swagger_v2/api_swagger_v2_detail_spec.rb +1 -1
- data/spec/swagger_v2/api_swagger_v2_extensions_spec.rb +22 -1
- data/spec/swagger_v2/api_swagger_v2_global_configuration_spec.rb +4 -1
- data/spec/swagger_v2/api_swagger_v2_hash_and_array_spec.rb +60 -0
- data/spec/swagger_v2/api_swagger_v2_headers_spec.rb +14 -9
- data/spec/swagger_v2/api_swagger_v2_hide_param_spec.rb +90 -0
- data/spec/swagger_v2/api_swagger_v2_param_type_body_nested_spec.rb +185 -110
- data/spec/swagger_v2/api_swagger_v2_param_type_body_spec.rb +11 -13
- data/spec/swagger_v2/api_swagger_v2_response_spec.rb +5 -5
- data/spec/swagger_v2/endpoint_versioned_path_spec.rb +19 -18
- data/spec/swagger_v2/namespaced_api_spec.rb +20 -0
- data/spec/swagger_v2/param_multi_type_spec.rb +73 -0
- data/spec/swagger_v2/param_type_spec.rb +54 -27
- data/spec/swagger_v2/params_array_spec.rb +96 -6
- data/spec/swagger_v2/params_nested_spec.rb +2 -2
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 96f5daf8e980cca96f1dc18f0a7dad2faf86b1f3
|
4
|
+
data.tar.gz: 665c50fb9409756ff95f526b2a13600a37db8a40
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f4e73ba96c6060cd24e22733de9160f267d72fdd9bc73f8baf76ecb6fe31ac908dab1506171ea6a9384631140ea338768fe7452513c6fbc9eb4a81ae70bc4819
|
7
|
+
data.tar.gz: 6d1a9f3df56f08ade9c36f43573a669b9a3a3c1172218cd02dc885dcee3e99897500249bcc5340b6cb4bb3dabafd098a1c529bd1ebf9e07eb50a212630409bb0
|
data/.rubocop.yml
CHANGED
data/.rubocop_todo.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -8,6 +8,30 @@
|
|
8
8
|
|
9
9
|
* Your contribution here.
|
10
10
|
|
11
|
+
### 0.22.0 (July 12, 2016)
|
12
|
+
|
13
|
+
#### Features
|
14
|
+
|
15
|
+
* [#470](https://github.com/ruby-grape/grape-swagger/pull/470): Document request definitions inline - [@LeFnord](https://github.com/LeFnord).
|
16
|
+
* [#448](https://github.com/ruby-grape/grape-swagger/pull/448): Header parameters are now prepended to the parameter list - [@anakinj](https://github.com/anakinj).
|
17
|
+
* [#444](https://github.com/ruby-grape/grape-swagger/pull/444): With multi types parameter the first type is use as the documentation type - [@scauglog](https://github.com/scauglog).
|
18
|
+
* [#463](https://github.com/ruby-grape/grape-swagger/pull/463): Added 'hidden' option for parameter to be exclude from generated documentation - [@anakinj](https://github.com/anakinj).
|
19
|
+
* [#471](https://github.com/ruby-grape/grape-swagger/pull/471): Allow Security Definitions Objects to be defined - [@bendodd](https://github.com/bendodd).
|
20
|
+
|
21
|
+
#### Fixes
|
22
|
+
|
23
|
+
* [#472](https://github.com/ruby-grape/grape-swagger/pull/472): Fixes required property for request definitions - [@LeFnord](https://github.com/LeFnord).
|
24
|
+
* [#467](https://github.com/ruby-grape/grape-swagger/pull/467): Refactors moving of body params - [@LeFnord](https://github.com/LeFnord).
|
25
|
+
* [#464](https://github.com/ruby-grape/grape-swagger/pull/464): Fixes array params, sets correct type and format for items - [@LeFnord](https://github.com/LeFnord).
|
26
|
+
* [#461](https://github.com/ruby-grape/grape-swagger/pull/461): Fixes issue by adding extensions to definitions. It appeared, if for the given status code, no definition could be found - [@LeFnord](https://github.com/LeFnord).
|
27
|
+
* [#455](https://github.com/ruby-grape/grape-swagger/pull/455): Setting `type:` option as `Array[Class]` creates `array` type in JSON - [@tyspring](https://github.com/tyspring).
|
28
|
+
* [#450](https://github.com/ruby-grape/grape-swagger/pull/438): Do not add :description to definitions if :description is missing on path - [@texpert](https://github.com/texpert).
|
29
|
+
* [#447](https://github.com/ruby-grape/grape-swagger/pull/447): Version part of the url is now ignored when generating tags for endpoint - [@anakinj](https://github.com/anakinj).
|
30
|
+
* [#444](https://github.com/ruby-grape/grape-swagger//pull/444): Default value provided in the documentation hash, override the grape default [@scauglog](https://github.com/scauglog).
|
31
|
+
* [#443](https://github.com/ruby-grape/grape-swagger/issues/443): Type provided in the documentation hash, override the grape type [@scauglog](https://github.com/scauglog).
|
32
|
+
* [#454](https://github.com/ruby-grape/grape-swagger/pull/454): Include documented Hashes in documentation output - [@aschuster3](https://github.com/aschuster3).
|
33
|
+
* [#457](https://github.com/ruby-grape/grape-swagger/issues/457): Using camel case on namespace throws exception on add_swagger_documentation method - [@rayko](https://github.com/rayko/).
|
34
|
+
|
11
35
|
### 0.21.0 (June 1, 2016)
|
12
36
|
|
13
37
|
#### Features
|
@@ -15,7 +39,6 @@
|
|
15
39
|
* [#413](https://github.com/ruby-grape/grape-swagger/pull/413): Move all model parsing logic to separate gems `grape-swagger-entity` and added representable parser `grape-swagger` - [@Bugagazavr](https://github.com/Bugagazavr).
|
16
40
|
* [#434](https://github.com/ruby-grape/grape-swagger/pull/434): Add summary to the operation object generator to be more compliant with [OpenAPI v2](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#operation-object) - [@aschuster3](https://github.com/aschuster3).
|
17
41
|
* [#441](https://github.com/ruby-grape/grape-swagger/pull/441): Accepting `String`, `lambda` and `proc` for `host` and `base_path` - [@LeFnord](https://github.com/LeFnord).
|
18
|
-
* Your contribution here.
|
19
42
|
|
20
43
|
#### Fixes
|
21
44
|
|
@@ -23,7 +46,6 @@
|
|
23
46
|
* [#419](https://github.com/ruby-grape/grape-swagger/pull/419): Replaced github ref to rubygems for external gems - [@Bugagazavr](https://github.com/Bugagazavr).
|
24
47
|
* [#420](https://github.com/ruby-grape/grape-swagger/pull/420): Raise SwaggerSpec exception if swagger spec isn't satisfied, when no parser for model is registered or response model is empty - [@Bugagazavr](https://github.com/Bugagazavr).
|
25
48
|
* [#438](https://github.com/ruby-grape/grape-swagger/pull/438): Route version was missing in :options passed to PathString, so Endpoint.path_and_definitions_objects wasn't returning a versioned path when required - [@texpert](https://github.com/texpert).
|
26
|
-
* Your contribution here.
|
27
49
|
|
28
50
|
### 0.20.3 (May 9, 2016)
|
29
51
|
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -49,7 +49,8 @@ grape-swagger | swagger spec | grape | grape-entity | represen
|
|
49
49
|
0.11.0 | 1.2 | >= 0.16.2 | < 0.5.0 | n/a |
|
50
50
|
0.20.1 | 2.0 | >= 0.12.0 ... <= 0.14.0 | <= 0.5.1 | n/a |
|
51
51
|
0.20.3 | 2.0 | >= 0.12.0 ... ~> 0.16.2 | ~> 0.5.1 | n/a |
|
52
|
-
0.21.0
|
52
|
+
0.21.0 | 2.0 | >= 0.12.0 ... <= 0.16.2 | <= 0.5.1 | >= 2.4.1 |
|
53
|
+
0.21.1 (next) | 2.0 | >= 0.12.0 ... <= 0.16.2 | <= 0.5.1 | >= 2.4.1 |
|
53
54
|
|
54
55
|
<a name="swagger-spec" />
|
55
56
|
## Swagger-Spec
|
@@ -191,6 +192,7 @@ end
|
|
191
192
|
* [add_version](#add_version)
|
192
193
|
* [doc_version](#doc_version)
|
193
194
|
* [markdown](#markdown)
|
195
|
+
* [security_definitions](#security_definitions)
|
194
196
|
* [models](#models)
|
195
197
|
* [hide_documentation_path](#hide_documentation_path)
|
196
198
|
* [info](#info)
|
@@ -272,12 +274,24 @@ add_swagger_documentation \
|
|
272
274
|
markdown: GrapeSwagger::Markdown::RedcarpetAdapter.new
|
273
275
|
```
|
274
276
|
|
277
|
+
<a name="security_definitions" />
|
278
|
+
#### security_definitions:
|
279
|
+
Specify the [Security Definitions Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-definitions-object)
|
280
|
+
|
281
|
+
```ruby
|
282
|
+
add_swagger_documentation \
|
283
|
+
security_definitions: {
|
284
|
+
api_key: {
|
285
|
+
type: "apiKey",
|
286
|
+
name: "api_key",
|
287
|
+
in: "header"
|
288
|
+
}
|
289
|
+
}
|
290
|
+
```
|
275
291
|
|
276
292
|
#### *authorizations*:
|
277
293
|
This value is added to the `authorizations` key in the JSON documentation.
|
278
294
|
|
279
|
-
|
280
|
-
|
281
295
|
<a name="models" />
|
282
296
|
#### models:
|
283
297
|
A list of entities to document. Combine with the [grape-entity](https://github.com/ruby-grape/grape-entity) gem.
|
@@ -343,9 +357,14 @@ add_swagger_documentation \
|
|
343
357
|
|
344
358
|
* [Swagger Header Parameters](#headers)
|
345
359
|
* [Hiding an Endpoint](#hiding)
|
360
|
+
* [Overriding Auto-Generated Nicknames](#overriding-auto-generated-nicknames)
|
346
361
|
* [Defining an endpoint as array](#array)
|
347
362
|
* [Using an options hash](#options)
|
348
363
|
* [Specify endpoint details](#details)
|
364
|
+
* [Overriding param type](#overriding-param-type)
|
365
|
+
* [Overriding type](#overriding-type)
|
366
|
+
* [Multi types](#multi-types)
|
367
|
+
* [Hiding parameters](#hiding-parameters)
|
349
368
|
* [Response documentation](#response)
|
350
369
|
|
351
370
|
|
@@ -453,6 +472,89 @@ post :act do
|
|
453
472
|
end
|
454
473
|
```
|
455
474
|
|
475
|
+
#### Overriding type
|
476
|
+
|
477
|
+
You can override type, using the documentation hash.
|
478
|
+
|
479
|
+
```ruby
|
480
|
+
params do
|
481
|
+
requires :input, type: String, documentation: { type: 'integer' }
|
482
|
+
end
|
483
|
+
post :act do
|
484
|
+
...
|
485
|
+
end
|
486
|
+
```
|
487
|
+
|
488
|
+
```json
|
489
|
+
{
|
490
|
+
"in": "formData",
|
491
|
+
"name": "input",
|
492
|
+
"type": "integer",
|
493
|
+
"format": "int32",
|
494
|
+
"required": true
|
495
|
+
}
|
496
|
+
```
|
497
|
+
|
498
|
+
#### Array type
|
499
|
+
|
500
|
+
Array types are also supported.
|
501
|
+
|
502
|
+
```ruby
|
503
|
+
params do
|
504
|
+
requires :action_ids, type: Array[Integer]
|
505
|
+
end
|
506
|
+
post :act do
|
507
|
+
...
|
508
|
+
end
|
509
|
+
```
|
510
|
+
|
511
|
+
```json
|
512
|
+
{
|
513
|
+
"in": "formData",
|
514
|
+
"name": "action_ids",
|
515
|
+
"type": "array",
|
516
|
+
"items": {
|
517
|
+
"type": "integer"
|
518
|
+
},
|
519
|
+
"required": true
|
520
|
+
}
|
521
|
+
```
|
522
|
+
|
523
|
+
#### Multi types
|
524
|
+
|
525
|
+
By default when you set multi types, the first type is selected as swagger type
|
526
|
+
|
527
|
+
```ruby
|
528
|
+
params do
|
529
|
+
requires :action, types: [String, Integer]
|
530
|
+
end
|
531
|
+
post :act do
|
532
|
+
...
|
533
|
+
end
|
534
|
+
```
|
535
|
+
|
536
|
+
```json
|
537
|
+
{
|
538
|
+
"in": "formData",
|
539
|
+
"name": "action",
|
540
|
+
"type": "string",
|
541
|
+
"required": true
|
542
|
+
}
|
543
|
+
```
|
544
|
+
|
545
|
+
#### Hiding parameters
|
546
|
+
|
547
|
+
Exclude single optional parameter from the documentation
|
548
|
+
|
549
|
+
```ruby
|
550
|
+
params do
|
551
|
+
optional :one, documentation: { hidden: true }
|
552
|
+
optional :two, documentation: { hidden: -> { true } }
|
553
|
+
end
|
554
|
+
post :act do
|
555
|
+
...
|
556
|
+
end
|
557
|
+
```
|
456
558
|
|
457
559
|
#### Overriding the route summary
|
458
560
|
|
data/example/api/endpoints.rb
CHANGED
@@ -23,21 +23,21 @@ module Api
|
|
23
23
|
namespace :splines do
|
24
24
|
#
|
25
25
|
desc 'Get all splines',
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
is_array: true,
|
27
|
+
http_codes: [
|
28
|
+
{ code: 200, message: 'get Splines', model: Api::Entities::Splines },
|
29
|
+
{ code: 422, message: 'SplinesOutError' }
|
30
|
+
]
|
31
31
|
get do
|
32
32
|
present :items, @@splines, with: Entities::Splines
|
33
33
|
end
|
34
34
|
|
35
35
|
#
|
36
36
|
desc 'Return a spline.',
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
37
|
+
http_codes: [
|
38
|
+
{ code: 200, message: 'get Splines' },
|
39
|
+
{ code: 422, message: 'SplinesOutError' }
|
40
|
+
]
|
41
41
|
params do
|
42
42
|
requires :id, type: Integer, desc: 'Spline id.'
|
43
43
|
end
|
@@ -49,9 +49,9 @@ module Api
|
|
49
49
|
|
50
50
|
#
|
51
51
|
desc 'Create a spline.',
|
52
|
-
|
53
|
-
|
54
|
-
|
52
|
+
http_codes: [
|
53
|
+
{ code: 201, message: 'Spline created', model: Api::Entities::Splines }
|
54
|
+
]
|
55
55
|
params do
|
56
56
|
requires :spline, type: Hash do
|
57
57
|
requires :x, type: Numeric
|
@@ -73,10 +73,10 @@ module Api
|
|
73
73
|
|
74
74
|
#
|
75
75
|
desc 'Update a spline.',
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
76
|
+
http_codes: [
|
77
|
+
{ code: 200, message: 'update Splines', model: Api::Entities::Splines },
|
78
|
+
{ code: 422, message: 'SplinesOutError' }
|
79
|
+
]
|
80
80
|
params do
|
81
81
|
requires :id, type: Integer, desc: 'Spline id.'
|
82
82
|
optional :spline, type: Hash do
|
data/lib/grape-swagger.rb
CHANGED
@@ -65,7 +65,6 @@ module Grape
|
|
65
65
|
next unless route_match
|
66
66
|
resource = route_match.captures.first
|
67
67
|
next if resource.empty?
|
68
|
-
resource.downcase!
|
69
68
|
@target_class.combined_routes[resource] ||= []
|
70
69
|
next if doc_klass.hide_documentation_path && route.path.match(/#{doc_klass.mount_path}($|\/|\(\.)/)
|
71
70
|
@target_class.combined_routes[resource] << route
|
@@ -102,6 +102,7 @@ module GrapeSwagger
|
|
102
102
|
hide_documentation_path: true,
|
103
103
|
format: :json,
|
104
104
|
authorizations: nil,
|
105
|
+
security_definitions: nil,
|
105
106
|
api_documentation: { desc: 'Swagger compatible API description' },
|
106
107
|
specific_api_documentation: { desc: 'Swagger compatible API description for specific API' }
|
107
108
|
}
|
@@ -3,9 +3,10 @@ module GrapeSwagger
|
|
3
3
|
class DataType
|
4
4
|
class << self
|
5
5
|
def call(value)
|
6
|
-
raw_data_type = value[:type]
|
7
|
-
raw_data_type
|
8
|
-
raw_data_type
|
6
|
+
raw_data_type = value.is_a?(Hash) ? value[:type] : value
|
7
|
+
raw_data_type ||= 'String'
|
8
|
+
raw_data_type = parse_multi_type(raw_data_type)
|
9
|
+
|
9
10
|
case raw_data_type.to_s
|
10
11
|
when 'Boolean', 'Date', 'Integer', 'String', 'Float', 'JSON', 'Array'
|
11
12
|
raw_data_type.to_s.downcase
|
@@ -28,6 +29,17 @@ module GrapeSwagger
|
|
28
29
|
end
|
29
30
|
end
|
30
31
|
|
32
|
+
def parse_multi_type(raw_data_type)
|
33
|
+
case raw_data_type
|
34
|
+
when /\A\[.*\]\z/
|
35
|
+
raw_data_type.gsub(/[(\A\[)(\s+)(\]\z)]/, '').split(',').first
|
36
|
+
when Array
|
37
|
+
raw_data_type.first
|
38
|
+
else
|
39
|
+
raw_data_type
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
31
43
|
def parse_entity_name(model)
|
32
44
|
if model.respond_to?(:entity_name)
|
33
45
|
model.entity_name
|
@@ -4,6 +4,7 @@ module GrapeSwagger
|
|
4
4
|
class << self
|
5
5
|
def add(path, definitions, route)
|
6
6
|
@route = route
|
7
|
+
|
7
8
|
description = route.settings[:description]
|
8
9
|
add_extension_to(path[method], extension(description)) if description && extended?(description, :x)
|
9
10
|
|
@@ -20,29 +21,32 @@ module GrapeSwagger
|
|
20
21
|
def_extension = extension(settings, :x_def)
|
21
22
|
|
22
23
|
if def_extension[:x_def].is_a?(Array)
|
23
|
-
def_extension[:x_def].each
|
24
|
-
next unless extension.key?(:for)
|
25
|
-
status = extension.delete(:for)
|
26
|
-
definition = find_definition(status, path)
|
27
|
-
add_extension_to(definitions[definition], x_def: extension)
|
28
|
-
end
|
24
|
+
def_extension[:x_def].each { |extension| setup_definition(extension, path, definitions) }
|
29
25
|
else
|
30
|
-
|
31
|
-
status = def_extension[:x_def].delete(:for)
|
32
|
-
definition = find_definition(status, path)
|
33
|
-
add_extension_to(definitions[definition], def_extension)
|
26
|
+
setup_definition(def_extension[:x_def], path, definitions)
|
34
27
|
end
|
35
28
|
end
|
36
29
|
|
30
|
+
def setup_definition(def_extension, path, definitions)
|
31
|
+
return unless def_extension.key?(:for)
|
32
|
+
status = def_extension[:for]
|
33
|
+
|
34
|
+
definition = find_definition(status, path)
|
35
|
+
add_extension_to(definitions[definition], x_def: def_extension)
|
36
|
+
end
|
37
|
+
|
37
38
|
def find_definition(status, path)
|
38
39
|
response = path[method][:responses][status]
|
40
|
+
return if response.nil?
|
39
41
|
|
40
|
-
response[:schema]['$ref'].split('/').last
|
42
|
+
return response[:schema]['$ref'].split('/').last if response[:schema].key?('$ref')
|
43
|
+
return response[:schema]['items']['$ref'].split('/').last if response[:schema].key?('items')
|
41
44
|
end
|
42
45
|
|
43
46
|
def add_extension_to(part, extensions)
|
47
|
+
return if part.nil?
|
44
48
|
concatenate(extensions).each do |key, value|
|
45
|
-
part[key] = value
|
49
|
+
part[key] = value unless key.start_with?('x-for')
|
46
50
|
end
|
47
51
|
end
|
48
52
|
|
@@ -2,159 +2,204 @@ module GrapeSwagger
|
|
2
2
|
module DocMethods
|
3
3
|
class MoveParams
|
4
4
|
class << self
|
5
|
-
|
5
|
+
attr_accessor :definitions
|
6
|
+
|
7
|
+
def can_be_moved?(params, http_verb)
|
8
|
+
move_methods.include?(http_verb) && includes_body_param?(params)
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_definition(params, route, definitions)
|
6
12
|
@definitions = definitions
|
13
|
+
unify!(params)
|
7
14
|
|
8
|
-
|
9
|
-
|
10
|
-
method_object = method_definition[verb]
|
15
|
+
params_to_move = movable_params(params)
|
16
|
+
params << parent_definition_of_params(params_to_move, route)
|
11
17
|
|
12
|
-
|
13
|
-
end
|
18
|
+
params
|
14
19
|
end
|
15
20
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
21
|
+
private
|
22
|
+
|
23
|
+
def parent_definition_of_params(params, route)
|
24
|
+
definition_name = GrapeSwagger::DocMethods::OperationId.manipulate(parse_model(route.path))
|
25
|
+
referenced_definition = build_definition(definition_name, params, route.request_method.downcase)
|
26
|
+
definition = @definitions[referenced_definition]
|
27
|
+
|
28
|
+
move_params_to_new(definition, params)
|
29
|
+
|
30
|
+
definition[:description] = route.description if route.respond_to?(:description)
|
31
|
+
|
32
|
+
build_body_parameter(referenced_definition, definition_name)
|
33
|
+
end
|
34
|
+
|
35
|
+
def move_params_to_new(definition, params)
|
36
|
+
params, nested_params = params.partition { |x| !x[:name].include?('[') }
|
37
|
+
|
38
|
+
unless params.blank?
|
39
|
+
properties, required = build_properties(params)
|
40
|
+
add_properties_to_definition(definition, properties, required)
|
20
41
|
end
|
42
|
+
|
43
|
+
nested_properties = build_nested_properties(nested_params) unless nested_params.blank?
|
44
|
+
add_properties_to_definition(definition, nested_properties, []) unless nested_params.blank?
|
21
45
|
end
|
22
46
|
|
23
|
-
def
|
24
|
-
|
47
|
+
def build_nested_properties(params, properties = {})
|
48
|
+
property = params.bsearch { |x| x[:name].include?('[') }[:name].split('[').first
|
25
49
|
|
26
|
-
|
27
|
-
|
50
|
+
nested_params, params = params.partition { |x| x[:name].start_with?("#{property}[") }
|
51
|
+
prepare_nested_names(property, nested_params)
|
28
52
|
|
29
|
-
|
53
|
+
recursive_call(properties, property, nested_params) unless nested_params.empty?
|
54
|
+
build_nested_properties(params, properties) unless params.empty?
|
30
55
|
|
31
|
-
|
32
|
-
|
56
|
+
properties
|
57
|
+
end
|
33
58
|
|
34
|
-
|
35
|
-
|
36
|
-
|
59
|
+
def recursive_call(properties, property, nested_params)
|
60
|
+
if should_expose_as_array?(nested_params)
|
61
|
+
properties[property] = array_type
|
62
|
+
move_params_to_new(properties[property][:items], nested_params)
|
37
63
|
else
|
38
|
-
|
39
|
-
|
64
|
+
properties[property] = object_type
|
65
|
+
move_params_to_new(properties[property], nested_params)
|
40
66
|
end
|
67
|
+
end
|
41
68
|
|
42
|
-
|
69
|
+
def movable_params(params)
|
70
|
+
to_delete = params.each_with_object([]) { |x, memo| memo << x if deletable?(x) }
|
71
|
+
delete_from(params, to_delete)
|
43
72
|
|
44
|
-
|
45
|
-
path[:parameters] << build_body_parameter(response.dup, name)
|
73
|
+
to_delete
|
46
74
|
end
|
47
75
|
|
48
|
-
def
|
49
|
-
|
50
|
-
|
76
|
+
def delete_from(params, to_delete)
|
77
|
+
to_delete.each { |x| params.delete(x) }
|
78
|
+
end
|
51
79
|
|
52
|
-
|
80
|
+
def add_properties_to_definition(definition, properties, required)
|
81
|
+
if definition.key?(:items)
|
82
|
+
definition[:items][:properties].merge!(properties)
|
83
|
+
add_to_required(definition[:items], required)
|
84
|
+
else
|
85
|
+
definition[:properties].merge!(properties)
|
86
|
+
add_to_required(definition, required)
|
87
|
+
end
|
88
|
+
end
|
53
89
|
|
54
|
-
|
55
|
-
|
90
|
+
def add_to_required(definition, value)
|
91
|
+
return if value.blank?
|
56
92
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
properties[name].tap do |x|
|
61
|
-
property_keys.each do |attribute|
|
62
|
-
x[attribute] = param[attribute] unless param[attribute].nil?
|
63
|
-
end
|
64
|
-
end
|
93
|
+
definition[:required] ||= []
|
94
|
+
definition[:required].push(*value)
|
95
|
+
end
|
65
96
|
|
66
|
-
|
67
|
-
|
97
|
+
def build_properties(params)
|
98
|
+
properties = {}
|
99
|
+
required = []
|
68
100
|
|
69
|
-
|
70
|
-
end
|
101
|
+
prepare_nested_types(params) if should_expose_as_array?(params)
|
71
102
|
|
72
|
-
|
73
|
-
|
74
|
-
|
103
|
+
params.each do |param|
|
104
|
+
name = param[:name].to_sym
|
105
|
+
properties[name] = {}
|
75
106
|
|
76
|
-
|
77
|
-
|
78
|
-
nested_name = params.bsearch { |x| x[:name].include?('[') }
|
79
|
-
return if nested_name.nil?
|
107
|
+
if should_expose_as_array?([param])
|
108
|
+
prepare_nested_types([param])
|
80
109
|
|
81
|
-
|
110
|
+
properties[name][:type] = 'array'
|
111
|
+
properties[name][:items] = {}
|
112
|
+
properties[name][:items].tap do |x|
|
113
|
+
property_keys.each do |attribute|
|
114
|
+
x[attribute] = param[attribute] unless param[attribute].nil?
|
115
|
+
end
|
116
|
+
end
|
117
|
+
else
|
82
118
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
119
|
+
properties[name].tap do |x|
|
120
|
+
property_keys.each do |attribute|
|
121
|
+
x[attribute] = param[attribute] unless param[attribute].nil?
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
88
125
|
|
89
|
-
|
90
|
-
build_definition(def_name)
|
91
|
-
@definitions[def_name][:description] = "#{name} - #{nested_name}"
|
92
|
-
move_params_to_new(def_name, nested)
|
126
|
+
required << name if deletable?(param) && param[:required]
|
93
127
|
end
|
94
|
-
end
|
95
128
|
|
96
|
-
|
129
|
+
[properties, required]
|
130
|
+
end
|
97
131
|
|
98
|
-
def build_body_parameter(
|
99
|
-
|
100
|
-
|
101
|
-
body_param.tap do |x|
|
102
|
-
x[:name] = entity
|
132
|
+
def build_body_parameter(reference, name)
|
133
|
+
{}.tap do |x|
|
134
|
+
x[:name] = name
|
103
135
|
x[:in] = 'body'
|
104
136
|
x[:required] = true
|
105
|
-
x[:schema] = { '$ref' =>
|
106
|
-
x[:schema] = { '$ref' => "#/definitions/#{name}" } if name
|
137
|
+
x[:schema] = { '$ref' => "#/definitions/#{reference}" }
|
107
138
|
end
|
108
139
|
end
|
109
140
|
|
110
|
-
def build_definition(name, verb = nil)
|
111
|
-
name = "#{verb}
|
112
|
-
@definitions[name] =
|
141
|
+
def build_definition(name, params, verb = nil)
|
142
|
+
name = "#{verb}#{name}" if verb
|
143
|
+
@definitions[name] = should_expose_as_array?(params) ? array_type : object_type
|
113
144
|
|
114
145
|
name
|
115
146
|
end
|
116
147
|
|
117
|
-
def
|
118
|
-
|
119
|
-
param.tap do |x|
|
120
|
-
name = x[:name].partition('[').last.sub(']', '')
|
121
|
-
name = name.partition('[').last.sub(']', '') if name.start_with?('[')
|
122
|
-
x[:name] = name
|
123
|
-
end
|
124
|
-
end
|
148
|
+
def array_type
|
149
|
+
{ type: 'array', items: { type: 'object', properties: {} } }
|
125
150
|
end
|
126
151
|
|
127
|
-
def
|
152
|
+
def object_type
|
153
|
+
{ type: 'object', properties: {} }
|
154
|
+
end
|
155
|
+
|
156
|
+
def prepare_nested_types(params)
|
128
157
|
params.each do |param|
|
129
|
-
param[:
|
130
|
-
param[:
|
158
|
+
next unless param[:items]
|
159
|
+
param[:type] = param[:items][:type] == 'array' ? 'string' : param[:items][:type]
|
160
|
+
param[:format] = param[:items][:format] if param[:items][:format]
|
161
|
+
param.delete(:items)
|
131
162
|
end
|
132
163
|
end
|
133
164
|
|
134
|
-
def
|
135
|
-
|
165
|
+
def prepare_nested_names(property, params)
|
166
|
+
params.each { |x| x[:name] = x[:name].sub(property, '').sub('[', '').sub(']', '') }
|
136
167
|
end
|
137
168
|
|
138
|
-
def
|
139
|
-
[:
|
169
|
+
def unify!(params)
|
170
|
+
params.each { |x| x[:in] = x.delete(:param_type) if x[:param_type] }
|
171
|
+
params.each { |x| x[:in] = 'body' if x[:in] == 'formData' } if includes_body_param?(params)
|
172
|
+
end
|
173
|
+
|
174
|
+
def parse_model(ref)
|
175
|
+
parts = ref.split('/')
|
176
|
+
parts.last.include?('{') ? parts[0..-2].join('/') : parts[0..-1].join('/')
|
140
177
|
end
|
141
178
|
|
142
179
|
def property_keys
|
143
180
|
[:type, :format, :description, :minimum, :maximum, :items]
|
144
181
|
end
|
145
182
|
|
146
|
-
def
|
147
|
-
|
148
|
-
false
|
183
|
+
def deletable?(param)
|
184
|
+
param[:in] == 'body'
|
149
185
|
end
|
150
186
|
|
151
|
-
def
|
152
|
-
|
187
|
+
def move_methods
|
188
|
+
[:post, :put, :patch, 'POST', 'PUT', 'PATCH']
|
189
|
+
end
|
190
|
+
|
191
|
+
def includes_body_param?(params)
|
192
|
+
params.map { |x| return true if x[:in] == 'body' || x[:param_type] == 'body' }
|
153
193
|
false
|
154
194
|
end
|
155
195
|
|
156
|
-
def
|
157
|
-
|
196
|
+
def should_expose_as_array?(params)
|
197
|
+
should_exposed_as(params) == 'array'
|
198
|
+
end
|
199
|
+
|
200
|
+
def should_exposed_as(params)
|
201
|
+
params.map { |x| return 'object' if x[:type] && x[:type] != 'array' }
|
202
|
+
'array'
|
158
203
|
end
|
159
204
|
end
|
160
205
|
end
|