grape-swagger 1.3.0 → 1.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +14 -0
  3. data/.github/workflows/rubocop.yml +26 -0
  4. data/.github/workflows/ruby.yml +30 -0
  5. data/.gitignore +1 -0
  6. data/.rspec +2 -0
  7. data/.rubocop.yml +10 -2
  8. data/.rubocop_todo.yml +1 -1
  9. data/CHANGELOG.md +39 -0
  10. data/Gemfile +3 -3
  11. data/README.md +113 -2
  12. data/UPGRADING.md +8 -0
  13. data/grape-swagger.gemspec +3 -3
  14. data/lib/grape-swagger/doc_methods/format_data.rb +3 -1
  15. data/lib/grape-swagger/doc_methods/move_params.rb +6 -7
  16. data/lib/grape-swagger/doc_methods/parse_params.rb +37 -5
  17. data/lib/grape-swagger/endpoint.rb +45 -6
  18. data/lib/grape-swagger/errors.rb +2 -0
  19. data/lib/grape-swagger/model_parsers.rb +2 -2
  20. data/lib/grape-swagger/rake/oapi_tasks.rb +1 -1
  21. data/lib/grape-swagger/version.rb +1 -1
  22. data/lib/grape-swagger.rb +5 -2
  23. data/spec/issues/537_enum_values_spec.rb +1 -0
  24. data/spec/issues/776_multiple_presents_spec.rb +59 -0
  25. data/spec/issues/809_utf8_routes_spec.rb +55 -0
  26. data/spec/issues/832_array_hash_float_decimal_spec.rb +111 -0
  27. data/spec/lib/format_data_spec.rb +24 -0
  28. data/spec/spec_helper.rb +1 -1
  29. data/spec/support/empty_model_parser.rb +2 -0
  30. data/spec/support/model_parsers/mock_parser.rb +16 -0
  31. data/spec/support/namespace_tags.rb +3 -0
  32. data/spec/support/the_paths_definitions.rb +4 -4
  33. data/spec/swagger_v2/api_swagger_v2_additional_properties_spec.rb +83 -0
  34. data/spec/swagger_v2/api_swagger_v2_mounted_spec.rb +1 -0
  35. data/spec/swagger_v2/api_swagger_v2_param_type_body_nested_spec.rb +73 -1
  36. data/spec/swagger_v2/api_swagger_v2_response_with_headers_spec.rb +4 -2
  37. data/spec/swagger_v2/api_swagger_v2_spec.rb +1 -0
  38. data/spec/swagger_v2/boolean_params_spec.rb +4 -1
  39. data/spec/swagger_v2/float_api_spec.rb +1 -0
  40. data/spec/swagger_v2/inheritance_and_discriminator_spec.rb +1 -0
  41. data/spec/swagger_v2/namespace_tags_prefix_spec.rb +1 -0
  42. data/spec/swagger_v2/param_multi_type_spec.rb +2 -0
  43. data/spec/swagger_v2/param_type_spec.rb +3 -0
  44. data/spec/swagger_v2/param_values_spec.rb +6 -0
  45. data/spec/swagger_v2/{params_array_collection_fromat_spec.rb → params_array_collection_format_spec.rb} +0 -0
  46. data/spec/swagger_v2/params_example_spec.rb +40 -0
  47. data/spec/swagger_v2/simple_mounted_api_spec.rb +3 -0
  48. metadata +21 -7
  49. data/.travis.yml +0 -40
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a3f65f49a31d6affe69a657daff3867582070436163992acb47f1166dde1cc6
4
- data.tar.gz: da9f13e2efd7e2b23dc92eea5b9deeaf4d9b8a860b13bae2b7f928b31d996be3
3
+ metadata.gz: 5d7b364d5b11e9fb35f7c67ce09c2953a7dd50da37cde1bc5b323bbdf9a3b6e4
4
+ data.tar.gz: 6c825fe6753c899c7f337253495677596acd40320e5e33f83c7c220e71e03e44
5
5
  SHA512:
6
- metadata.gz: 0d51d5cde5ff558fefcbf8b4503d290bc535c48f22d1ee3c2662ad406c548b7ef72d196b36598b2d3ea68d6ebef8e6ce43e3dec8dab6f371df9d12aaadd34567
7
- data.tar.gz: b22301456da8cd150767fd614434bfad161959eb0836b028b4ff8d15893fd128c53513e87ab8180a6442b8fda9ec41a6e6648b67cb32a46b692d2b117e229ec1
6
+ metadata.gz: d5e2a5c0d06216c3e2a474051b5986a9f8343a351714b3e255396bbef3984704d85436218fa87e39f0988fbb18b3f5227b2531d514a788f4a4b131028dc19de2
7
+ data.tar.gz: 6bd210a20332285224d0d24036b9892c729fc84c435991b3e36dd81d8d1976d4ae35c406d3e9d742a82bd90acac75903355c6a827380870e6f1deb2af0b17b7f
@@ -0,0 +1,14 @@
1
+ # To get started with Dependabot version updates, you'll need to specify which
2
+ # package ecosystems to update and where the package manifests are located.
3
+ # Please see the documentation for all configuration options:
4
+ # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5
+
6
+ version: 2
7
+ updates:
8
+ - package-ecosystem: "bundler" # See documentation for possible values
9
+ directory: "/" # Location of package manifests
10
+ schedule:
11
+ interval: "weekly"
12
+ day: "friday"
13
+ assignees:
14
+ - "LeFnord"
@@ -0,0 +1,26 @@
1
+ name: Rubocop
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - '*'
7
+ pull_request:
8
+ branches:
9
+ - '*'
10
+
11
+ jobs:
12
+ rubocop:
13
+ name: Rubocop
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v2
17
+ - uses: actions/setup-ruby@v1
18
+ with:
19
+ ruby-version: '3.0'
20
+ - run: gem install rubocop --no-doc
21
+ - run: rubocop --format progress --format json --out rubocop.json
22
+ id: rubocop
23
+ - uses: duderman/rubocop-annotate-action@v0.1.0
24
+ with:
25
+ path: rubocop.json
26
+ if: ${{ failure() }}
@@ -0,0 +1,30 @@
1
+ name: Ruby
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - '*'
7
+ pull_request:
8
+ branches:
9
+ - '*'
10
+
11
+ jobs:
12
+ rspec:
13
+ runs-on: ubuntu-latest
14
+ strategy:
15
+ matrix:
16
+ ruby-version: ['2.6', '2.7', '3.0', 'head']
17
+ grape-version: [1.6.0, 1.5.3]
18
+ model-parser: [grape-swagger-entity, grape-swagger-representable, '']
19
+
20
+ steps:
21
+ - uses: actions/checkout@v2
22
+ - name: Set up Ruby
23
+ uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
24
+ with:
25
+ ruby-version: ${{ matrix.ruby-version }}
26
+ GRAPE_VERSION: ${{ matrix.grape-version }}
27
+ MODEL_PARSER: ${{ matrix.model-parser }}
28
+ bundler-cache: true
29
+ - name: Run rspec
30
+ run: bundle exec rspec
data/.gitignore CHANGED
@@ -42,3 +42,4 @@ spec/params_entity_spec.rb
42
42
  vendor/bundle/
43
43
  spec/swagger_v2/x-dummy.rb
44
44
  coverage/
45
+ .byebug_history
data/.rspec CHANGED
@@ -1 +1,3 @@
1
1
  --color
2
+ --profile
3
+ --format documentation
data/.rubocop.yml CHANGED
@@ -5,7 +5,8 @@ AllCops:
5
5
  - vendor/**/*
6
6
  - example/**/*
7
7
  NewCops: enable
8
- TargetRubyVersion: 2.7
8
+ TargetRubyVersion: 3.0
9
+ SuggestExtensions: false
9
10
 
10
11
  # Layout stuff
11
12
  #
@@ -28,6 +29,10 @@ Layout/SpaceAroundMethodCallOperator:
28
29
 
29
30
  # Lint stuff
30
31
  #
32
+ Lint/ConstantDefinitionInBlock:
33
+ Exclude:
34
+ - spec/**/*
35
+
31
36
  Lint/DeprecatedOpenSSLConstant:
32
37
  Enabled: true
33
38
 
@@ -50,7 +55,7 @@ Metrics/BlockLength:
50
55
  - spec/**/*
51
56
 
52
57
  Metrics/ClassLength:
53
- Max: 300
58
+ Max: 350
54
59
 
55
60
  Metrics/CyclomaticComplexity:
56
61
  Max: 17
@@ -69,6 +74,9 @@ Naming:
69
74
  Style/AccessorGrouping:
70
75
  Enabled: true
71
76
 
77
+ Style/AsciiComments:
78
+ Enabled: false
79
+
72
80
  Style/ArrayCoercion:
73
81
  Enabled: true
74
82
 
data/.rubocop_todo.yml CHANGED
@@ -28,7 +28,7 @@ Metrics/MethodLength:
28
28
 
29
29
  # Offense count: 7
30
30
  Metrics/PerceivedComplexity:
31
- Max: 14
31
+ Max: 16
32
32
 
33
33
  # Offense count: 3
34
34
  Style/ClassVars:
data/CHANGELOG.md CHANGED
@@ -9,6 +9,45 @@
9
9
  * Your contribution here.
10
10
 
11
11
 
12
+ ### 1.4.2 (October 22, 2021)
13
+
14
+ #### Fixes
15
+
16
+ * [#840](https://github.com/ruby-grape/grape-swagger/pull/840): Fixes documentation of `additionalProperties` field when used with array parameters, or when setting it to `false` - [@magni-](https://github.com/magni-)
17
+ * [#841](https://github.com/ruby-grape/grape-swagger/pull/839): Fixes `type` and `format` values for object fields nested in an array ([#832](https://github.com/ruby-grape/grape-swagger/issue/832)) - [@magni-](https://github.com/magni-)
18
+ * [#839](https://github.com/ruby-grape/grape-swagger/pull/839): Fixes documentation of `false` or `nil` default parameter values - [@magni-](https://github.com/magni-)
19
+
20
+
21
+ ### 1.4.1 (September 15, 2021)
22
+
23
+ #### Fixes
24
+
25
+ * [#833](https://github.com/ruby-grape/grape-swagger/pull/833): Fixes issue of examples not showing for `in: 'body'` parameters - [@stevenou](https://github.com/stevenou)
26
+
27
+
28
+ ### 1.4.0 (March 20, 2021)
29
+
30
+ #### Features
31
+
32
+ * [#818](https://github.com/ruby-grape/grape-swagger/pull/818): Adds ruby 3.0 support - [@LeFnord](https://github.com/LeFnord).
33
+ * [#815](https://github.com/ruby-grape/grape-swagger/pull/815): Add required for multiple presents - [@MaximeRDY](https://github.com/MaximeRDY).
34
+
35
+ #### Fixes
36
+
37
+ * [#822](https://github.com/ruby-grape/grape-swagger/pull/822): Corrected the related parameter lookup on request params - [@Jack12816](https://github.com/Jack12816).
38
+
39
+
40
+ ### 1.3.1 (November 1, 2020)
41
+
42
+ #### Features
43
+
44
+ * [#813](https://github.com/ruby-grape/grape-swagger/pull/813): Handle multiple presents - [@AntoineGuestin](https://github.com/AntoineGuestin).
45
+
46
+ #### Fixes
47
+
48
+ * [#811](https://github.com/ruby-grape/grape-swagger/pull/811): Fixes #809: supports utf8 route names - [@LeFnord](https://github.com/LeFnord).
49
+
50
+
12
51
  ### 1.3.0 (September 3, 2020)
13
52
 
14
53
  #### 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.4.0'
9
+ gem 'grape', case version = ENV['GRAPE_VERSION'] || '>= 1.5.0'
10
10
  when 'HEAD'
11
11
  { git: 'https://github.com/ruby-grape/grape' }
12
12
  else
@@ -27,13 +27,13 @@ group :development, :test do
27
27
  gem 'rake'
28
28
  gem 'rdoc'
29
29
  gem 'rspec', '~> 3.9'
30
- gem 'rubocop', '~> 0.90', require: false
30
+ gem 'rubocop', '~> 1.0', require: false
31
31
  end
32
32
 
33
33
  group :test do
34
34
  gem 'coveralls_reborn', require: false
35
35
 
36
- gem 'ruby-grape-danger', '~> 0.1.1', require: false
36
+ gem 'ruby-grape-danger', '~> 0.2.0', require: false
37
37
  gem 'simplecov', require: false
38
38
 
39
39
  unless ENV['MODEL_PARSER'] == 'grape-swagger-entity'
data/README.md CHANGED
@@ -451,6 +451,8 @@ add_swagger_documentation \
451
451
  * [Collection Format](#collection-format)
452
452
  * [Hiding parameters](#hiding-parameters)
453
453
  * [Setting a Swagger default value](#default-value)
454
+ * [Setting `additionalProperties` for `object`-type parameters](#additional-properties)
455
+ * [Example parameter value](#param-example)
454
456
  * [Response documentation](#response)
455
457
  * [Changing default status codes](#change-status)
456
458
  * [File response](#file-response)
@@ -458,6 +460,7 @@ add_swagger_documentation \
458
460
  * [Response examples documentation](#response-examples)
459
461
  * [Response headers documentation](#response-headers)
460
462
  * [Adding root element to responses](#response-root)
463
+ * [Multiple present Response](#multiple-response)
461
464
 
462
465
  #### Swagger Header Parameters <a name="headers"></a>
463
466
 
@@ -768,8 +771,6 @@ params do
768
771
  end
769
772
  ```
770
773
 
771
- The example parameter will populate the Swagger UI with the example value, and can be used for optional or required parameters.
772
-
773
774
  Grape uses the option `default` to set a default value for optional parameters. This is different in that Grape will set your parameter to the provided default if the parameter is omitted, whereas the example value above will only set the value in the UI itself. This will set the Swagger `defaultValue` to the provided value. Note that the example value will override the Grape default value.
774
775
 
775
776
  ```ruby
@@ -779,6 +780,46 @@ params do
779
780
  end
780
781
  ```
781
782
 
783
+ ### Setting `additionalProperties` for `object`-type parameters <a name="additional-properties">
784
+
785
+ Use the `additional_properties` option in the `documentation` hash for `object`-type parameters to set [`additionalProperties`](https://swagger.io/specification/v2/#model-with-mapdictionary-properties).
786
+
787
+ #### Allow any additional properties
788
+ ```ruby
789
+ params do
790
+ optional :thing, type: Hash, documentation: { additional_properties: true }
791
+ end
792
+ ```
793
+
794
+ #### Allow any additional properties of a particular type
795
+ ```ruby
796
+ params do
797
+ optional :thing, type: Hash, documentation: { additional_properties: String }
798
+ end
799
+ ```
800
+
801
+ #### Allow any additional properties matching a defined schema
802
+ ```ruby
803
+ class Entity < Grape::Entity
804
+ expose :this
805
+ end
806
+
807
+ params do
808
+ optional :thing, type: Hash, documentation: { additional_properties: Entity }
809
+ end
810
+ ```
811
+
812
+
813
+ #### Example parameter value <a name="param-example"></a>
814
+
815
+ The example parameter will populate the Swagger UI with the example value, and can be used for optional or required parameters.
816
+
817
+ ```ruby
818
+ params do
819
+ requires :id, type: Integer, documentation: { example: 123 }
820
+ optional :name, type String, documentation: { example: 'Buddy Guy' }
821
+ end
822
+ ```
782
823
 
783
824
  #### Expose nested namespace as standalone route
784
825
 
@@ -1262,6 +1303,76 @@ The result will look like following:
1262
1303
  }
1263
1304
  }
1264
1305
  ```
1306
+ #### Multiple present Response <a name="multiple-response"></a>
1307
+
1308
+ You can specify a custom multiple response by using the `as` key:
1309
+ ```ruby
1310
+ desc 'Multiple response',
1311
+ success: [
1312
+ { model: Entities::EnumValues, as: :gender },
1313
+ { model: Entities::Something, as: :somethings }
1314
+ ]
1315
+ end
1316
+
1317
+ get '/things' do
1318
+ ...
1319
+ end
1320
+ ```
1321
+ The result will look like following:
1322
+ ```
1323
+ "responses": {
1324
+ "200": {
1325
+ "description": "Multiple response",
1326
+ "schema":{
1327
+ "type":"object",
1328
+ "properties":{
1329
+ "gender":{
1330
+ "$ref":"#/definitions/EnumValues"
1331
+ },
1332
+ "somethings":{
1333
+ "$ref":"#/definitions/Something"
1334
+ }
1335
+ }
1336
+ }
1337
+ }
1338
+ }
1339
+ ```
1340
+ You can also specify if the response is an array, with the `is_array` key:
1341
+ ```ruby
1342
+ desc 'Multiple response with array',
1343
+ success: [
1344
+ { model: Entities::EnumValues, as: :gender },
1345
+ { model: Entities::Something, as: :somethings, is_array: true, required: true }
1346
+ ]
1347
+ end
1348
+
1349
+ get '/things' do
1350
+ ...
1351
+ end
1352
+ ```
1353
+ The result will look like following:
1354
+ ```
1355
+ "responses": {
1356
+ "200": {
1357
+ "description": "Multiple response with array",
1358
+ "schema":{
1359
+ "type":"object",
1360
+ "properties":{
1361
+ "gender":{
1362
+ "$ref":"#/definitions/EnumValues"
1363
+ },
1364
+ "somethings":{
1365
+ "type":"array",
1366
+ "items":{
1367
+ "$ref":"#/definitions/Something"
1368
+ }
1369
+ }
1370
+ },
1371
+ "required": ["somethings"]
1372
+ }
1373
+ }
1374
+ }
1375
+ ```
1265
1376
 
1266
1377
  ## Using Grape Entities <a name="grape-entity"></a>
1267
1378
 
data/UPGRADING.md CHANGED
@@ -1,5 +1,13 @@
1
1
  ## Upgrading Grape-swagger
2
2
 
3
+ ### Upgrading to >= 1.4.2
4
+
5
+ - `additionalProperties` has been deprecated and will be removed in a future version of `grape-swagger`. It has been replaced with `additional_properties`.
6
+
7
+ ### Upgrading to >= 1.4.0
8
+
9
+ - Official support for ruby < 2.5 removed, ruby 2.5 only in testing mode, but no support.
10
+
3
11
  ### Upgrading to >= 1.3.0
4
12
 
5
13
  - The model (entity) description no longer comes from the route description. It will have a default value: `<<EntityName>> model`.
@@ -7,13 +7,13 @@ Gem::Specification.new do |s|
7
7
  s.name = 'grape-swagger'
8
8
  s.version = GrapeSwagger::VERSION
9
9
  s.platform = Gem::Platform::RUBY
10
- s.authors = ['Tim Vandecasteele']
11
- s.email = ['tim.vandecasteele@gmail.com']
10
+ s.authors = ['LeFnord', 'Tim Vandecasteele']
11
+ s.email = ['pscholz.le@gmail.com', 'tim.vandecasteele@gmail.com']
12
12
  s.homepage = 'https://github.com/ruby-grape/grape-swagger'
13
13
  s.summary = 'Add auto generated documentation to your Grape API that can be displayed with Swagger.'
14
14
  s.license = 'MIT'
15
15
 
16
- s.required_ruby_version = '>= 2.4'
16
+ s.required_ruby_version = '>= 2.5'
17
17
  s.add_runtime_dependency 'grape', '~> 1.3'
18
18
 
19
19
  s.files = `git ls-files`.split("\n")
@@ -7,7 +7,7 @@ module GrapeSwagger
7
7
  def to_format(parameters)
8
8
  parameters.reject { |parameter| parameter[:in] == 'body' }.each do |b|
9
9
  related_parameters = parameters.select do |p|
10
- p[:name] != b[:name] && p[:name].to_s.include?("#{b[:name].to_s.gsub(/\[\]\z/, '')}[")
10
+ p[:name] != b[:name] && p[:name].to_s.start_with?("#{b[:name].to_s.gsub(/\[\]\z/, '')}[")
11
11
  end
12
12
  parameters.reject! { |p| p[:name] == b[:name] } if move_down(b, related_parameters)
13
13
  end
@@ -35,6 +35,8 @@ module GrapeSwagger
35
35
 
36
36
  def add_array(parameter, related_parameters)
37
37
  related_parameters.each do |p|
38
+ next if p.key?(:items)
39
+
38
40
  p_type = p[:type] == 'array' ? 'string' : p[:type]
39
41
  p[:items] = { type: p_type, format: p[:format], enum: p[:enum], is_array: p[:is_array] }
40
42
  p[:items].delete_if { |_k, v| v.nil? }
@@ -103,9 +103,9 @@ module GrapeSwagger
103
103
 
104
104
  def document_as_property(param)
105
105
  property_keys.each_with_object({}) do |x, memo|
106
- value = param[x]
107
- next if value.blank?
106
+ next unless param.key?(x)
108
107
 
108
+ value = param[x]
109
109
  if x == :type && @definitions[value].present?
110
110
  memo['$ref'] = "#/definitions/#{value}"
111
111
  else
@@ -181,7 +181,8 @@ module GrapeSwagger
181
181
  end
182
182
 
183
183
  def property_keys
184
- %i[type format description minimum maximum items enum default additionalProperties]
184
+ %i[type format description minimum maximum items enum default additional_properties additionalProperties
185
+ example]
185
186
  end
186
187
 
187
188
  def deletable?(param)
@@ -193,8 +194,7 @@ module GrapeSwagger
193
194
  end
194
195
 
195
196
  def includes_body_param?(params)
196
- params.map { |x| return true if x[:in] == 'body' || x[:param_type] == 'body' }
197
- false
197
+ params.any? { |x| x[:in] == 'body' || x[:param_type] == 'body' }
198
198
  end
199
199
 
200
200
  def should_expose_as_array?(params)
@@ -202,8 +202,7 @@ module GrapeSwagger
202
202
  end
203
203
 
204
204
  def should_exposed_as(params)
205
- params.map { |x| return 'object' if x[:type] && x[:type] != 'array' }
206
- 'array'
205
+ params.any? { |x| x[:type] && x[:type] != 'array' } ? 'object' : 'array'
207
206
  end
208
207
  end
209
208
  end
@@ -25,8 +25,9 @@ module GrapeSwagger
25
25
  document_default_value(settings) unless value_type[:is_array]
26
26
  document_range_values(settings) unless value_type[:is_array]
27
27
  document_required(settings)
28
- document_additional_properties(settings)
28
+ document_additional_properties(definitions, settings) unless value_type[:is_array]
29
29
  document_add_extensions(settings)
30
+ document_example(settings)
30
31
 
31
32
  @parsed_param
32
33
  end
@@ -50,7 +51,7 @@ module GrapeSwagger
50
51
  end
51
52
 
52
53
  def document_default_value(settings)
53
- @parsed_param[:default] = settings[:default] if settings[:default].present?
54
+ @parsed_param[:default] = settings[:default] if settings.key?(:default)
54
55
  end
55
56
 
56
57
  def document_type_and_format(settings, data_type)
@@ -104,12 +105,43 @@ module GrapeSwagger
104
105
 
105
106
  array_items[:default] = value_type[:default] if value_type[:default].present?
106
107
 
108
+ set_additional_properties, additional_properties = parse_additional_properties(definitions, value_type)
109
+ array_items[:additionalProperties] = additional_properties if set_additional_properties
110
+
107
111
  array_items
108
112
  end
109
113
 
110
- def document_additional_properties(settings)
111
- additional_properties = settings[:additionalProperties]
112
- @parsed_param[:additionalProperties] = additional_properties if additional_properties
114
+ def document_additional_properties(definitions, settings)
115
+ set_additional_properties, additional_properties = parse_additional_properties(definitions, settings)
116
+ @parsed_param[:additionalProperties] = additional_properties if set_additional_properties
117
+ end
118
+
119
+ def parse_additional_properties(definitions, settings)
120
+ return false unless settings.key?(:additionalProperties) || settings.key?(:additional_properties)
121
+
122
+ value =
123
+ if settings.key?(:additionalProperties)
124
+ GrapeSwagger::Errors::SwaggerSpecDeprecated.tell!(:additionalProperties)
125
+ settings[:additionalProperties]
126
+ else
127
+ settings[:additional_properties]
128
+ end
129
+
130
+ parsed_value =
131
+ if definitions[value.to_s]
132
+ { '$ref': "#/definitions/#{value}" }
133
+ elsif value.is_a?(Class)
134
+ { type: DataType.call(value) }
135
+ else
136
+ value
137
+ end
138
+
139
+ [true, parsed_value]
140
+ end
141
+
142
+ def document_example(settings)
143
+ example = settings[:example]
144
+ @parsed_param[:example] = example if example
113
145
  end
114
146
 
115
147
  def param_type(value_type)
@@ -201,8 +201,7 @@ module Grape
201
201
  def response_object(route, options)
202
202
  codes(route).each_with_object({}) do |value, memo|
203
203
  value[:message] ||= ''
204
- memo[value[:code]] = { description: value[:message] }
205
-
204
+ memo[value[:code]] = { description: value[:message] ||= '' } unless memo[value[:code]].present?
206
205
  memo[value[:code]][:headers] = value[:headers] if value[:headers]
207
206
 
208
207
  next build_file_response(memo[value[:code]]) if file_response?(value[:model])
@@ -221,7 +220,7 @@ module Grape
221
220
  next if response_model.start_with?('Swagger_doc')
222
221
 
223
222
  @definitions[response_model][:description] ||= "#{response_model} model"
224
- memo[value[:code]][:schema] = build_reference(route, value, response_model, options)
223
+ build_memo_schema(memo, route, value, response_model, options)
225
224
  memo[value[:code]][:examples] = value[:examples] if value[:examples]
226
225
  end
227
226
  end
@@ -268,15 +267,52 @@ module Grape
268
267
 
269
268
  private
270
269
 
270
+ def build_memo_schema(memo, route, value, response_model, options)
271
+ if memo[value[:code]][:schema] && value[:as]
272
+ memo[value[:code]][:schema][:properties].merge!(build_reference(route, value, response_model, options))
273
+
274
+ if value[:required]
275
+ memo[value[:code]][:schema][:required] ||= []
276
+ memo[value[:code]][:schema][:required] << value[:as].to_s
277
+ end
278
+
279
+ elsif value[:as]
280
+ memo[value[:code]][:schema] = {
281
+ type: :object,
282
+ properties: build_reference(route, value, response_model, options)
283
+ }
284
+ memo[value[:code]][:schema][:required] = [value[:as].to_s] if value[:required]
285
+ else
286
+ memo[value[:code]][:schema] = build_reference(route, value, response_model, options)
287
+ end
288
+ end
289
+
271
290
  def build_reference(route, value, response_model, settings)
272
291
  # TODO: proof that the definition exist, if model isn't specified
273
- reference = { '$ref' => "#/definitions/#{response_model}" }
292
+ reference = if value.key?(:as)
293
+ { value[:as] => build_reference_hash(response_model) }
294
+ else
295
+ build_reference_hash(response_model)
296
+ end
274
297
  return reference unless value[:code] < 300
275
298
 
276
- reference = { type: 'array', items: reference } if route.options[:is_array]
299
+ if value.key?(:as) && value.key?(:is_array)
300
+ reference[value[:as]] = build_reference_array(reference[value[:as]])
301
+ elsif route.options[:is_array]
302
+ reference = build_reference_array(reference)
303
+ end
304
+
277
305
  build_root(route, reference, response_model, settings)
278
306
  end
279
307
 
308
+ def build_reference_hash(response_model)
309
+ { '$ref' => "#/definitions/#{response_model}" }
310
+ end
311
+
312
+ def build_reference_array(reference)
313
+ { type: 'array', items: reference }
314
+ end
315
+
280
316
  def build_root(route, reference, response_model, settings)
281
317
  default_root = response_model.underscore
282
318
  default_root = default_root.pluralize if route.options[:is_array]
@@ -293,7 +329,7 @@ module Grape
293
329
  end
294
330
 
295
331
  def file_response?(value)
296
- value.to_s.casecmp('file').zero? ? true : false
332
+ value.to_s.casecmp('file').zero?
297
333
  end
298
334
 
299
335
  def build_file_response(memo)
@@ -382,6 +418,9 @@ module Grape
382
418
  default_code[:message] = entity[:message] || route.description || default_code[:message].sub('{item}', @item)
383
419
  default_code[:examples] = entity[:examples] if entity[:examples]
384
420
  default_code[:headers] = entity[:headers] if entity[:headers]
421
+ default_code[:as] = entity[:as] if entity[:as]
422
+ default_code[:is_array] = entity[:is_array] if entity[:is_array]
423
+ default_code[:required] = entity[:required] if entity[:required]
385
424
  else
386
425
  default_code = GrapeSwagger::DocMethods::StatusCodes.get[route.request_method.downcase.to_sym]
387
426
  default_code[:model] = entity if entity
@@ -3,7 +3,9 @@
3
3
  module GrapeSwagger
4
4
  module Errors
5
5
  class UnregisteredParser < StandardError; end
6
+
6
7
  class SwaggerSpec < StandardError; end
8
+
7
9
  class SwaggerSpecDeprecated < SwaggerSpec
8
10
  class << self
9
11
  def tell!(what)
@@ -16,14 +16,14 @@ module GrapeSwagger
16
16
  subhash = @parsers.except(klass).to_a
17
17
  insert_at = subhash.index(subhash.assoc(before_klass))
18
18
  insert_at = subhash.length - 1 if insert_at.nil?
19
- @parsers = Hash[subhash.insert(insert_at, [klass, ancestor])]
19
+ @parsers = subhash.insert(insert_at, [klass, ancestor]).to_h
20
20
  end
21
21
 
22
22
  def insert_after(after_klass, klass, ancestor)
23
23
  subhash = @parsers.except(klass).to_a
24
24
  insert_at = subhash.index(subhash.assoc(after_klass))
25
25
  insert_at = subhash.length - 1 if insert_at.nil?
26
- @parsers = Hash[subhash.insert(insert_at + 1, [klass, ancestor])]
26
+ @parsers = subhash.insert(insert_at + 1, [klass, ancestor]).to_h
27
27
  end
28
28
 
29
29
  def each
@@ -64,7 +64,7 @@ module GrapeSwagger
64
64
  ::Rake::Task['oapi:fetch'].invoke
65
65
  exit if error?
66
66
 
67
- output = system "swagger validate #{file}"
67
+ output = system "swagger-cli validate #{file}"
68
68
 
69
69
  $stdout.puts 'install swagger-cli with `npm install swagger-cli -g`' if output.nil?
70
70
  FileUtils.rm(file)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GrapeSwagger
4
- VERSION = '1.3.0'
4
+ VERSION = '1.4.2'
5
5
  end