grape-swagger 2.1.2 → 2.1.3

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.
data/README.md CHANGED
@@ -3,22 +3,92 @@
3
3
  [![Coverage Status](https://coveralls.io/repos/github/ruby-grape/grape-swagger/badge.svg?branch=master)](https://coveralls.io/github/ruby-grape/grape-swagger?branch=master)
4
4
  [![Code Climate](https://codeclimate.com/github/ruby-grape/grape-swagger.svg)](https://codeclimate.com/github/ruby-grape/grape-swagger)
5
5
 
6
- ##### Table of Contents
7
-
8
- * [What is grape-swagger?](#what)
9
- * [Related Projects](#related)
10
- * [Compatibility](#version)
11
- * [Swagger-Spec](#swagger-spec)
12
- * [Installation](#install)
13
- * [Usage](#usage)
14
- * [Model Parsers](#model_parsers)
15
- * [Configure](#configure)
16
- * [Routes Configuration](#routes)
17
- * [Using Grape Entities](#grape-entity)
18
- * [Securing the Swagger UI](#oauth)
19
- * [Example](#example)
20
- * [Rake Tasks](#rake)
21
-
6
+ # Table of Contents
7
+
8
+ - [What is grape-swagger? ](#what-is-grape-swagger-)
9
+ - [Related Projects ](#related-projects-)
10
+ - [Compatibility ](#compatibility-)
11
+ - [Swagger-Spec ](#swagger-spec-)
12
+ - [Installation ](#installation-)
13
+ - [Upgrade](#upgrade)
14
+ - [Usage ](#usage-)
15
+ - [Model Parsers ](#model-parsers-)
16
+ - [Custom Model Parsers](#custom-model-parsers)
17
+ - [insert_before](#insert_before)
18
+ - [insert_after](#insert_after)
19
+ - [CORS](#cors)
20
+ - [Configure ](#configure-)
21
+ - [host: ](#host-)
22
+ - [base_path: ](#base_path-)
23
+ - [mount_path: ](#mount_path-)
24
+ - [add_base_path: ](#add_base_path-)
25
+ - [add_root: ](#add_root-)
26
+ - [add_version: ](#add_version-)
27
+ - [doc_version: ](#doc_version-)
28
+ - [endpoint_auth_wrapper: ](#endpoint_auth_wrapper-)
29
+ - [swagger_endpoint_guard: ](#swagger_endpoint_guard-)
30
+ - [token_owner: ](#token_owner-)
31
+ - [security_definitions: ](#security_definitions-)
32
+ - [security: ](#security-)
33
+ - [models: ](#models-)
34
+ - [tags: ](#tags-)
35
+ - [hide_documentation_path: (default: true) ](#hide_documentation_path-default-true-)
36
+ - [info: ](#info-)
37
+ - [array_use_braces: ](#array_use_braces-)
38
+ - [api_documentation](#api_documentation)
39
+ - [specific_api_documentation](#specific_api_documentation)
40
+ - [consumes](#consumes)
41
+ - [produces](#produces)
42
+ - [Routes Configuration ](#routes-configuration-)
43
+ - [Swagger Header Parameters ](#swagger-header-parameters--)
44
+ - [Hiding an Endpoint ](#hiding-an-endpoint-)
45
+ - [Overriding Auto-Generated Nicknames ](#overriding-auto-generated-nicknames-)
46
+ - [Specify endpoint details ](#specify-endpoint-details-)
47
+ - [Overriding the route summary ](#overriding-the-route-summary-)
48
+ - [Overriding the tags ](#overriding-the-tags-)
49
+ - [Deprecating routes ](#deprecating-routes-)
50
+ - [Overriding the name of the body parameter ](#overriding-the-name-of-the-body-parameter-)
51
+ - [Defining an endpoint as an array ](#defining-an-endpoint-as-an-array-)
52
+ - [Using an options hash ](#using-an-options-hash-)
53
+ - [Overriding parameter type ](#overriding-parameter-type-)
54
+ - [Overriding data type of the parameter ](#overriding-data-type-of-the-parameter-)
55
+ - [Multiple types ](#multiple-types-)
56
+ - [Array of data type ](#array-of-data-type-)
57
+ - [Collection format of arrays ](#collection-format-of-arrays-)
58
+ - [Hiding parameters ](#hiding-parameters-)
59
+ - [Setting a Swagger default value ](#setting-a-swagger-default-value-)
60
+ - [Setting additionalProperties for object-type parameters ](#setting-additionalproperties-for-object-type-parameters-)
61
+ - [Allow any additional properties](#allow-any-additional-properties)
62
+ - [Allow any additional properties of a particular type](#allow-any-additional-properties-of-a-particular-type)
63
+ - [Allow any additional properties matching a defined schema](#allow-any-additional-properties-matching-a-defined-schema)
64
+ - [Example parameter value ](#example-parameter-value-)
65
+ - [Expose nested namespace as standalone route](#expose-nested-namespace-as-standalone-route)
66
+ - [With a custom name](#with-a-custom-name)
67
+ - [Response documentation ](#response-documentation-)
68
+ - [Changing default status codes ](#changing-default-status-codes-)
69
+ - [Multiple status codes for response ](#multiple-status-codes-for-response-)
70
+ - [File response ](#file-response-)
71
+ - [Default response ](#default-response-)
72
+ - [Extensions ](#extensions-)
73
+ - [Response examples documentation ](#response-examples-documentation-)
74
+ - [Response headers documentation ](#response-headers-documentation-)
75
+ - [Adding root element to responses ](#adding-root-element-to-responses-)
76
+ - [Multiple present Response ](#multiple-present-response-)
77
+ - [Using Grape Entities ](#using-grape-entities-)
78
+ - [Documented class/definition](#documented-classdefinition)
79
+ - [Relationships](#relationships)
80
+ - [1xN](#1xn)
81
+ - [1x1](#1x1)
82
+ - [Inheritance with allOf and discriminator](#inheritance-with-allof-and-discriminator)
83
+ - [Securing the Swagger UI ](#securing-the-swagger-ui-)
84
+ - [Example ](#example-)
85
+ - [Grouping the API list using Namespace](#grouping-the-api-list-using-namespace)
86
+ - [Example Code](#example-code)
87
+ - [Rake Tasks ](#rake-tasks-)
88
+ - [OpenApi/Swagger Documentation](#openapiswagger-documentation)
89
+ - [OpenApi/Swagger Validation](#openapiswagger-validation)
90
+ - [Contributing to grape-swagger](#contributing-to-grape-swagger)
91
+ - [Copyright and License](#copyright-and-license)
22
92
 
23
93
  ## What is grape-swagger? <a name="what"></a>
24
94
 
@@ -43,18 +113,19 @@ This screenshot is based on the [Hussars](https://github.com/LeFnord/hussars) sa
43
113
 
44
114
  The following versions of grape, grape-entity and grape-swagger can currently be used together.
45
115
 
46
- | grape-swagger | swagger spec | grape | grape-entity | representable |
47
- | ------------------ | ------------ | ----------------------- | ------------ | ------------- |
48
- | 0.10.5 | 1.2 | >= 0.10.0 ... <= 0.14.0 | < 0.5.0 | n/a |
49
- | 0.11.0 | 1.2 | >= 0.16.2 | < 0.5.0 | n/a |
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 ... <= 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 |
54
- | 0.34.0 | 2.0 | >= 0.16.2 ... < 1.3.0 | >= 0.5.0 | >= 2.4.1 |
55
- | >= 1.0.0 | 2.0 | >= 1.3.0 | >= 0.5.0 | >= 2.4.1 |
56
- | >= 2.0.0 | 2.0 | >= 1.7.0 | >= 0.5.0 | >= 2.4.1 |
57
- | >= 2.0.0 ... < 2.2 | 2.0 | >= 1.8.0 ... < 2.3.0 | >= 0.5.0 | >= 2.4.1 |
116
+ | grape-swagger | swagger spec | grape | grape-entity | representable |
117
+ | --------------------- | ------------ | ----------------------- | ------------ | ------------- |
118
+ | 0.10.5 | 1.2 | >= 0.10.0 ... <= 0.14.0 | < 0.5.0 | n/a |
119
+ | 0.11.0 | 1.2 | >= 0.16.2 | < 0.5.0 | n/a |
120
+ | 0.25.2 | 2.0 | >= 0.14.0 ... <= 0.18.0 | <= 0.6.0 | >= 2.4.1 |
121
+ | 0.26.0 | 2.0 | >= 0.16.2 ... <= 1.1.0 | <= 0.6.1 | >= 2.4.1 |
122
+ | 0.27.0 | 2.0 | >= 0.16.2 ... <= 1.1.0 | >= 0.5.0 | >= 2.4.1 |
123
+ | 0.32.0 | 2.0 | >= 0.16.2 | >= 0.5.0 | >= 2.4.1 |
124
+ | 0.34.0 | 2.0 | >= 0.16.2 ... < 1.3.0 | >= 0.5.0 | >= 2.4.1 |
125
+ | >= 1.0.0 | 2.0 | >= 1.3.0 | >= 0.5.0 | >= 2.4.1 |
126
+ | >= 2.0.0 | 2.0 | >= 1.7.0 | >= 0.5.0 | >= 2.4.1 |
127
+ | >= 2.0.0 ... <= 2.1.2 | 2.0 | >= 1.8.0 ... < 2.3.0 | >= 0.5.0 | >= 2.4.1 |
128
+ | > 2.1.2 | 2.0 | >= 1.8.0 ... < 4.0 | >= 0.5.0 | >= 2.4.1 |
58
129
 
59
130
 
60
131
  ## Swagger-Spec <a name="swagger-spec"></a>
@@ -1446,7 +1517,6 @@ The result will look like following:
1446
1517
  Add the [grape-entity](https://github.com/ruby-grape/grape-entity) and [grape-swagger-entity](https://github.com/ruby-grape/grape-swagger-entity) gem to your Gemfile.
1447
1518
 
1448
1519
  The following example exposes statuses. And exposes statuses documentation adding :type, :desc and :required.
1449
- The documented class/definition name could be set via `#entity_name`.
1450
1520
 
1451
1521
  ```ruby
1452
1522
  module API
@@ -1489,6 +1559,57 @@ module API
1489
1559
  end
1490
1560
  ```
1491
1561
 
1562
+ ### Documented class/definition
1563
+
1564
+ You can set the name of the Entity when being documented via `#entity_name`:
1565
+
1566
+ ```ruby
1567
+ module API
1568
+ module Entities
1569
+ class Status < Grape::Entity
1570
+ expose :text, documentation: { type: 'string', desc: 'Status update text.', required: true }
1571
+ end
1572
+
1573
+ class Link < Grape::Entity
1574
+ expose :href, documentation: { type: 'url' }
1575
+
1576
+ def self.entity_name
1577
+ 'LinkedStatus'
1578
+ end
1579
+
1580
+ end
1581
+ end
1582
+ end
1583
+ ```
1584
+ Should generate the following definitions in your swagger json:
1585
+
1586
+ ```json
1587
+ {
1588
+ "definitions": {
1589
+ "API_Entities_Status": {
1590
+ "type": "object",
1591
+ "properties": {
1592
+ "text": {
1593
+ "type": "string",
1594
+ "description": "Status update text.",
1595
+ },
1596
+ },
1597
+ "required": [
1598
+ "text",
1599
+ ],
1600
+ "description": "API_Entities_Pet model"
1601
+ },
1602
+ "LinkedStatus": {
1603
+ "type": "object",
1604
+ "properties": {
1605
+ "href": {
1606
+ "type": "url",
1607
+ },
1608
+ "description": "LinkedStatus model"
1609
+ }
1610
+ }
1611
+ }
1612
+ ```
1492
1613
 
1493
1614
  ### Relationships
1494
1615
 
data/RELEASING.md CHANGED
@@ -16,7 +16,7 @@ Check that the last build succeeded in [Travis CI](https://travis-ci.org/ruby-gr
16
16
  Change "Next" in [CHANGELOG.md](CHANGELOG.md) to the current date.
17
17
 
18
18
  ```
19
- ### 0.7.2 (February 6, 2014)
19
+ ### 2.2.0 (2025-11-21)
20
20
  ```
21
21
 
22
22
  Remove the lines with "Your contribution here.", since there will be no more contributions to this release.
@@ -25,7 +25,7 @@ Commit your changes.
25
25
 
26
26
  ```
27
27
  git add CHANGELOG.md lib/grape-swagger/version.rb
28
- git commit -m "Preparing for release, 0.7.2."
28
+ git commit -m "Preparing for release, 2.2.0."
29
29
  git push origin master
30
30
  ```
31
31
 
@@ -34,10 +34,10 @@ Release.
34
34
  ```
35
35
  $ rake release
36
36
 
37
- grape-swagger 0.7.2 built to pkg/grape-swagger-0.7.2.gem.
38
- Tagged v0.7.2.
37
+ grape-swagger 2.2.0 built to pkg/grape-swagger-2.2.0.gem.
38
+ Tagged v2.2.0.
39
39
  Pushed git commits and tags.
40
- Pushed grape-swagger 0.7.2 to rubygems.org.
40
+ Pushed grape-swagger 2.2.0 to rubygems.org.
41
41
  ```
42
42
 
43
43
  ### Prepare for the Next Version
@@ -47,7 +47,7 @@ Increment the minor version, the third number, modify [lib/grape-swagger/version
47
47
  Add the next release to [CHANGELOG.md](CHANGELOG.md).
48
48
 
49
49
  ```
50
- ### 0.7.3 (Next)
50
+ ### 2.2.1 (Next)
51
51
 
52
52
  #### Features
53
53
 
@@ -62,7 +62,7 @@ Commit your changes.
62
62
 
63
63
  ```
64
64
  git add CHANGELOG.md lib/grape-swagger/version.rb
65
- git commit -m "Preparing for next developer iteration, 0.7.3."
65
+ git commit -m "Preparing for next developer iteration, 2.2.1."
66
66
  git push origin master
67
67
  ```
68
68
 
@@ -71,7 +71,7 @@ git push origin master
71
71
  Make an announcement on the [ruby-grape@googlegroups.com](mailto:ruby-grape@googlegroups.com) mailing list. The general format is as follows.
72
72
 
73
73
  ```
74
- Grape-Swagger 0.7.2 has been released.
74
+ Grape-Swagger 2.2.0 has been released.
75
75
 
76
76
  There were 8 contributors to this release, not counting documentation.
77
77
 
@@ -15,8 +15,7 @@ Gem::Specification.new do |s|
15
15
  s.metadata['rubygems_mfa_required'] = 'true'
16
16
 
17
17
  s.required_ruby_version = '>= 3.1'
18
- s.add_dependency 'grape', '>= 1.7', '< 3.0'
19
- s.add_dependency 'rack-test', '~> 2'
18
+ s.add_dependency 'grape', '>= 1.7', '< 4.0'
20
19
 
21
20
  s.files = Dir['lib/**/*', '*.md', 'LICENSE.txt', 'grape-swagger.gemspec']
22
21
  s.require_paths = ['lib']
@@ -22,7 +22,7 @@ module GrapeSwagger
22
22
  }
23
23
  else
24
24
  properties, required = parsed_response
25
- unless properties&.any?
25
+ if properties.nil?
26
26
  raise GrapeSwagger::Errors::SwaggerSpec,
27
27
  "Empty model #{model_name}, swagger 2.0 doesn't support empty definitions."
28
28
  end
@@ -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.start_with?("#{b[:name].to_s.gsub(/\[\]\z/, '')}[")
10
+ p[:name] != b[:name] && p[:name].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
@@ -163,7 +163,7 @@ module GrapeSwagger
163
163
  end
164
164
 
165
165
  def prepare_nested_names(property, params)
166
- params.each { |x| x[:name] = x[:name].sub(property, '').sub('[', '').sub(']', '') }
166
+ params.each { |x| x[:name] = x[:name].sub(property.to_s, '').sub('[', '').sub(']', '') }
167
167
  end
168
168
 
169
169
  def unify!(params)
@@ -141,8 +141,10 @@ module GrapeSwagger
141
141
  end
142
142
 
143
143
  def document_example(settings)
144
- example = settings[:example]
145
- @parsed_param[:example] = example if example
144
+ return unless settings.key?(:example)
145
+
146
+ key = @parsed_param[:in] == 'body' ? :example : :'x-example'
147
+ @parsed_param[key] = settings[:example]
146
148
  end
147
149
 
148
150
  def param_type(value_type, consumes)
@@ -11,7 +11,6 @@ require 'grape-swagger/doc_methods/path_string'
11
11
  require 'grape-swagger/doc_methods/tag_name_description'
12
12
  require 'grape-swagger/doc_methods/parse_params'
13
13
  require 'grape-swagger/doc_methods/move_params'
14
- require 'grape-swagger/doc_methods/headers'
15
14
  require 'grape-swagger/doc_methods/build_model_definition'
16
15
  require 'grape-swagger/doc_methods/version'
17
16
 
@@ -2,7 +2,10 @@
2
2
 
3
3
  require 'active_support'
4
4
  require 'active_support/core_ext/string/inflections'
5
- require 'grape-swagger/endpoint/params_parser'
5
+ require_relative 'request_param_parsers/headers'
6
+ require_relative 'request_param_parsers/route'
7
+ require_relative 'request_param_parsers/body'
8
+ require_relative 'token_owner_resolver'
6
9
 
7
10
  module Grape
8
11
  class Endpoint # rubocop:disable Metrics/ClassLength
@@ -12,9 +15,7 @@ module Grape
12
15
  if content_types.empty?
13
16
  formats = [target_class.format, target_class.default_format].compact.uniq
14
17
  formats = GrapeSwagger::FORMATTER_DEFAULTS.keys if formats.empty?
15
- content_types = GrapeSwagger::CONTENT_TYPE_DEFAULTS.select do |content_type, _mime_type|
16
- formats.include? content_type
17
- end.values
18
+ content_types = formats.filter_map { |f| GrapeSwagger::CONTENT_TYPE_DEFAULTS[f] }
18
19
  end
19
20
 
20
21
  content_types.uniq
@@ -383,45 +384,15 @@ module Grape
383
384
  end
384
385
 
385
386
  def build_request_params(route, settings)
386
- required = merge_params(route)
387
- required = GrapeSwagger::DocMethods::Headers.parse(route) + required unless route.headers.nil?
388
-
389
- default_type(required)
390
-
391
- request_params = GrapeSwagger::Endpoint::ParamsParser.parse_request_params(required, settings, self)
392
-
393
- request_params.empty? ? required : request_params
394
- end
395
-
396
- def merge_params(route)
397
- path_params = get_path_params(route.app&.inheritable_setting&.namespace_stackable)
398
- param_keys = route.params.keys
399
-
400
- # Merge path params options into route params
401
- route_params = route.params
402
- route_params.each_key do |key|
403
- path = path_params[key] || {}
404
- params = route_params[key]
405
- params = {} unless params.is_a? Hash
406
- route_params[key] = path.merge(params)
387
+ GrapeSwagger.request_param_parsers.each_with_object({}) do |parser_klass, accum|
388
+ params = parser_klass.parse(
389
+ route,
390
+ accum,
391
+ settings,
392
+ self
393
+ )
394
+ accum.merge!(params.stringify_keys)
407
395
  end
408
-
409
- route_params.delete_if { |key| key.is_a?(String) && param_keys.include?(key.to_sym) }.to_a
410
- end
411
-
412
- # Iterates over namespaces recursively
413
- # to build a hash of path params with options, including type
414
- def get_path_params(stackable_values)
415
- params = {}
416
- return param unless stackable_values
417
- return params unless stackable_values.is_a? Grape::Util::StackableValues
418
-
419
- stackable_values&.new_values&.dig(:namespace)&.each do |namespace| # rubocop:disable Style/SafeNavigationChainLength
420
- space = namespace.space.to_s.gsub(':', '')
421
- params[space] = namespace.options || {}
422
- end
423
- inherited_params = get_path_params(stackable_values.inherited_values)
424
- inherited_params.merge(params)
425
396
  end
426
397
 
427
398
  def default_type(params)
@@ -469,7 +440,10 @@ module Grape
469
440
  route_hidden = route.options[:hidden] if route.options.key?(:hidden)
470
441
  return route_hidden unless route_hidden.is_a?(Proc)
471
442
 
472
- options[:token_owner] ? route_hidden.call(send(options[:token_owner].to_sym)) : route_hidden.call
443
+ return route_hidden.call unless options[:token_owner]
444
+
445
+ token_owner = GrapeSwagger::TokenOwnerResolver.resolve(self, options[:token_owner])
446
+ GrapeSwagger::TokenOwnerResolver.evaluate_proc(route_hidden, token_owner)
473
447
  end
474
448
 
475
449
  def hidden_parameter?(value)
@@ -13,5 +13,7 @@ module GrapeSwagger
13
13
  end
14
14
  end
15
15
  end
16
+
17
+ class TokenOwnerNotFound < NoMethodError; end
16
18
  end
17
19
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'request_param_parsers/headers'
4
+ require_relative 'request_param_parsers/route'
5
+ require_relative 'request_param_parsers/body'
6
+
7
+ module GrapeSwagger
8
+ class RequestParamParserRegistry
9
+ DEFAULT_PARSERS = [
10
+ GrapeSwagger::RequestParamParsers::Headers,
11
+ GrapeSwagger::RequestParamParsers::Route,
12
+ GrapeSwagger::RequestParamParsers::Body
13
+ ].freeze
14
+
15
+ include Enumerable
16
+
17
+ def initialize
18
+ @parsers = DEFAULT_PARSERS.dup
19
+ end
20
+
21
+ def register(klass)
22
+ remove_parser(klass)
23
+ @parsers << klass
24
+ end
25
+
26
+ def insert_before(before_klass, klass)
27
+ remove_parser(klass)
28
+ insert_at = @parsers.index(before_klass) || @parsers.size
29
+ @parsers.insert(insert_at, klass)
30
+ end
31
+
32
+ def insert_after(after_klass, klass)
33
+ remove_parser(klass)
34
+ insert_at = @parsers.index(after_klass)
35
+ @parsers.insert(insert_at ? insert_at + 1 : @parsers.size, klass)
36
+ end
37
+
38
+ def each(&)
39
+ @parsers.each(&)
40
+ end
41
+
42
+ private
43
+
44
+ def remove_parser(klass)
45
+ @parsers.reject! { |k| k == klass }
46
+ end
47
+ end
48
+ end
@@ -1,27 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GrapeSwagger
4
- module Endpoint
5
- class ParamsParser
6
- attr_reader :params, :settings, :endpoint
4
+ module RequestParamParsers
5
+ class Body
6
+ attr_reader :route, :params, :settings, :endpoint
7
7
 
8
- def self.parse_request_params(params, settings, endpoint)
9
- new(params, settings, endpoint).parse_request_params
8
+ def self.parse(route, params, settings, endpoint)
9
+ new(route, params, settings, endpoint).parse
10
10
  end
11
11
 
12
- def initialize(params, settings, endpoint)
12
+ def initialize(_route, params, settings, endpoint)
13
13
  @params = params
14
14
  @settings = settings
15
15
  @endpoint = endpoint
16
16
  end
17
17
 
18
- def parse_request_params
18
+ def parse
19
19
  public_params.each_with_object({}) do |(name, options), memo|
20
20
  name = name.to_s
21
- param_type = options[:type]
22
- param_type = param_type.to_s unless param_type.nil?
21
+ param_type = options[:type]&.to_s
23
22
 
24
- if param_type_is_array?(param_type)
23
+ if array_param?(param_type)
25
24
  options[:is_array] = true
26
25
  name += '[]' if array_use_braces?
27
26
  end
@@ -36,8 +35,8 @@ module GrapeSwagger
36
35
  @array_use_braces ||= settings[:array_use_braces] && !includes_body_param?
37
36
  end
38
37
 
39
- def param_type_is_array?(param_type)
40
- return false unless param_type
38
+ def array_param?(param_type)
39
+ return false if param_type.nil?
41
40
  return true if param_type == 'Array'
42
41
 
43
42
  param_types = param_type.match(/\[(.*)\]$/)
@@ -48,21 +47,14 @@ module GrapeSwagger
48
47
  end
49
48
 
50
49
  def public_params
51
- params.select { |param| public_parameter?(param) }
50
+ params.select { |_key, param| public_parameter?(param) }
52
51
  end
53
52
 
54
- def public_parameter?(param)
55
- param_options = param.last
53
+ def public_parameter?(param_options)
56
54
  return true unless param_options.key?(:documentation) && !param_options[:required]
57
55
 
58
56
  param_hidden = param_options[:documentation].fetch(:hidden, false)
59
- if param_hidden.is_a?(Proc)
60
- param_hidden = if settings[:token_owner]
61
- param_hidden.call(endpoint.send(settings[:token_owner].to_sym))
62
- else
63
- param_hidden.call
64
- end
65
- end
57
+ param_hidden = evaluate_hidden_proc(param_hidden) if param_hidden.is_a?(Proc)
66
58
  !param_hidden
67
59
  end
68
60
 
@@ -71,6 +63,13 @@ module GrapeSwagger
71
63
  options.dig(:documentation, :param_type) == 'body' || options.dig(:documentation, :in) == 'body'
72
64
  end
73
65
  end
66
+
67
+ def evaluate_hidden_proc(hidden_proc)
68
+ return hidden_proc.call unless settings[:token_owner]
69
+
70
+ token_owner = GrapeSwagger::TokenOwnerResolver.resolve(endpoint, settings[:token_owner])
71
+ GrapeSwagger::TokenOwnerResolver.evaluate_proc(hidden_proc, token_owner)
72
+ end
74
73
  end
75
74
  end
76
75
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GrapeSwagger
4
+ module RequestParamParsers
5
+ class Headers
6
+ attr_reader :route
7
+
8
+ def self.parse(route, params, settings, endpoint)
9
+ new(route, params, settings, endpoint).parse
10
+ end
11
+
12
+ def initialize(route, _params, _settings, _endpoint)
13
+ @route = route
14
+ end
15
+
16
+ def parse
17
+ return {} unless route.headers
18
+
19
+ route.headers.each_with_object({}) do |(name, definition), accum|
20
+ # Extract the description from any key type (string or symbol)
21
+ description = definition[:description] || definition['description']
22
+ doc = { desc: description, in: 'header' }
23
+
24
+ header_attrs = definition.symbolize_keys.except(:description, 'description')
25
+ header_attrs[:type] = definition[:type].titleize if definition[:type]
26
+ header_attrs[:documentation] = doc
27
+
28
+ accum[name] = header_attrs
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GrapeSwagger
4
+ module RequestParamParsers
5
+ class Route
6
+ DEFAULT_PARAM_TYPE = { required: true, type: 'Integer' }.freeze
7
+
8
+ attr_reader :route
9
+
10
+ def self.parse(route, params, settings, endpoint)
11
+ new(route, params, settings, endpoint).parse
12
+ end
13
+
14
+ def initialize(route, _params, _settings, _endpoint)
15
+ @route = route
16
+ end
17
+
18
+ def parse
19
+ stackable_values = route.app&.inheritable_setting&.namespace_stackable
20
+
21
+ path_params = build_path_params(stackable_values)
22
+
23
+ fulfill_params(path_params)
24
+ end
25
+
26
+ private
27
+
28
+ def build_path_params(stackable_values)
29
+ params = {}
30
+
31
+ while stackable_values.is_a?(Grape::Util::StackableValues)
32
+ params.merge!(fetch_inherited_params(stackable_values))
33
+ stackable_values = stackable_values.inherited_values
34
+ end
35
+
36
+ params
37
+ end
38
+
39
+ def fetch_inherited_params(stackable_values)
40
+ return {} unless stackable_values.new_values
41
+
42
+ namespaces = stackable_values.new_values[:namespace] || []
43
+
44
+ namespaces.each_with_object({}) do |namespace, params|
45
+ space = namespace.space.to_s.gsub(':', '')
46
+ params[space] = namespace.options || {}
47
+ end
48
+ end
49
+
50
+ def fulfill_params(path_params)
51
+ # Merge path params options into route params
52
+ route.params.each_with_object({}) do |(param, definition), accum|
53
+ # The route.params hash includes both parametrized params (with a string as a key)
54
+ # and well-defined params from body/query (with a symbol as a key).
55
+ # We avoid overriding well-defined params with parametrized ones.
56
+ key = param.is_a?(String) ? param.to_sym : param
57
+ next if param.is_a?(String) && accum.key?(key)
58
+
59
+ defined_options = definition.is_a?(Hash) ? definition : {}
60
+ value = (path_params[param] || {}).merge(defined_options)
61
+ accum[key] = value.empty? ? DEFAULT_PARAM_TYPE : value
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end