grape-swagger 2.0.3 → 2.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c36235d1ec48b00075496c2d59151a87e42f2b7f34c876db913504a7706c1a70
4
- data.tar.gz: 0d7aac2f325422f53218257e4cb8e2bef51e73e424a53d88b244c3073c614656
3
+ metadata.gz: 8fbf69e7e7bc7f3a836c574fe91df74abb10aab05c778cee716398d76afeace6
4
+ data.tar.gz: 5ab4bc60eafa3ad32959a040aed645943121912037a738278d88fb649390a0fa
5
5
  SHA512:
6
- metadata.gz: 13d4c18cf80ce43aedde8a3347be17ebda40fd6e2b56496459226f350e273b31cd6c74d79d75b68e2461d47dd6f0aeaec3080709aebbcf5b6beb9b8162f949bb
7
- data.tar.gz: 949ebd6da1fcdb3c398e6070a035f50a9e211ed27a93694b275f5e09a9d1266c675f04f7b1e9583329689fcc9a38fd50cdac8dd6c1de87c486016e63faacce57
6
+ metadata.gz: 8bcb10791418aa79af266d503f7fd5130157bb7971d7acb094964981d9ee8635fe6bcf72e212b81f22a25f2032a002fba99b97a7d078d8d35a908f0117fae379
7
+ data.tar.gz: d7843b9aaf70d83a9d0de3dc7f075b8f3df2e4cedda4a1c519cbc4109dc9da1cb1de82c9966fcf6a0083ebbe22a89c13654fbd9fe9e1156af4103e8bc70a344e
data/CHANGELOG.md CHANGED
@@ -9,6 +9,18 @@
9
9
  * Your contribution here.
10
10
 
11
11
 
12
+ ### 2.1.0 (May 14, 2024)
13
+
14
+ #### Features
15
+
16
+ * [#927](https://github.com/ruby-grape/grape-swagger/pull/927): Set default parameter location based on consumes - [@spaceraccoon](https://github.com/spaceraccoon)
17
+ * [#929](https://github.com/ruby-grape/grape-swagger/pull/929): Set query parameter for array of primitive types - [@spaceraccoon](https://github.com/spaceraccoon)
18
+
19
+ #### Fixes
20
+
21
+ * [#926](https://github.com/ruby-grape/grape-swagger/pull/926): Refactor route and namespace combination logic - [@numbata](https://github.com/numbata)
22
+
23
+
12
24
  ### 2.0.3 (April 26, 2024)
13
25
 
14
26
  #### Fixes
@@ -75,6 +75,14 @@ module GrapeSwagger
75
75
  PRIMITIVE_MAPPINGS.keys.map(&:downcase)
76
76
  end
77
77
 
78
+ def query_array_primitive?(type)
79
+ query_array_primitives.include?(type.to_s.downcase)
80
+ end
81
+
82
+ def query_array_primitives
83
+ primitives << 'string'
84
+ end
85
+
78
86
  def mapping(value)
79
87
  PRIMITIVE_MAPPINGS[value] || 'string'
80
88
  end
@@ -4,7 +4,7 @@ module GrapeSwagger
4
4
  module DocMethods
5
5
  class ParseParams
6
6
  class << self
7
- def call(param, settings, path, route, definitions)
7
+ def call(param, settings, path, route, definitions, consumes) # rubocop:disable Metrics/ParameterLists
8
8
  method = route.request_method
9
9
  additional_documentation = settings.fetch(:documentation, {})
10
10
  settings.merge!(additional_documentation)
@@ -14,7 +14,7 @@ module GrapeSwagger
14
14
 
15
15
  # required properties
16
16
  @parsed_param = {
17
- in: param_type(value_type),
17
+ in: param_type(value_type, consumes),
18
18
  name: settings[:full_name] || param
19
19
  }
20
20
 
@@ -70,21 +70,17 @@ module GrapeSwagger
70
70
 
71
71
  def document_array_param(value_type, definitions)
72
72
  if value_type[:documentation].present?
73
- param_type = value_type[:documentation][:param_type] || value_type[:documentation][:in]
74
73
  doc_type = value_type[:documentation][:type]
75
74
  type = DataType.mapping(doc_type) if doc_type && !DataType.request_primitive?(doc_type)
76
75
  collection_format = value_type[:documentation][:collectionFormat]
77
76
  end
78
77
 
79
- param_type ||= value_type[:param_type]
80
-
81
78
  array_items = parse_array_item(
82
79
  definitions,
83
80
  type,
84
81
  value_type
85
82
  )
86
83
 
87
- @parsed_param[:in] = param_type || 'formData'
88
84
  @parsed_param[:items] = array_items
89
85
  @parsed_param[:type] = 'array'
90
86
  @parsed_param[:collectionFormat] = collection_format if DataType.collections.include?(collection_format)
@@ -148,14 +144,20 @@ module GrapeSwagger
148
144
  @parsed_param[:example] = example if example
149
145
  end
150
146
 
151
- def param_type(value_type)
147
+ def param_type(value_type, consumes)
152
148
  param_type = value_type[:param_type] || value_type[:in]
153
- if value_type[:path].include?("{#{value_type[:param_name]}}")
149
+ if !value_type[:is_array] && value_type[:path].include?("{#{value_type[:param_name]}}")
154
150
  'path'
155
151
  elsif param_type
156
152
  param_type
157
153
  elsif %w[POST PUT PATCH].include?(value_type[:method])
158
- DataType.request_primitive?(value_type[:data_type]) ? 'formData' : 'body'
154
+ if consumes.include?('application/x-www-form-urlencoded') || consumes.include?('multipart/form-data')
155
+ 'formData'
156
+ else
157
+ 'body'
158
+ end
159
+ elsif value_type[:is_array] && !DataType.query_array_primitive?(value_type[:data_type])
160
+ 'formData'
159
161
  else
160
162
  'query'
161
163
  end
@@ -119,7 +119,7 @@ module Grape
119
119
  method[:description] = description_object(route)
120
120
  method[:produces] = produces_object(route, options[:produces] || options[:format])
121
121
  method[:consumes] = consumes_object(route, options[:consumes] || options[:format])
122
- method[:parameters] = params_object(route, options, path)
122
+ method[:parameters] = params_object(route, options, path, method[:consumes])
123
123
  method[:security] = security_object(route)
124
124
  method[:responses] = response_object(route, options)
125
125
  method[:tags] = route.options.fetch(:tags, tag_object(route, path))
@@ -175,7 +175,7 @@ module Grape
175
175
  GrapeSwagger::DocMethods::ProducesConsumes.call(route.settings.dig(:description, :consumes) || format)
176
176
  end
177
177
 
178
- def params_object(route, options, path)
178
+ def params_object(route, options, path, consumes)
179
179
  parameters = build_request_params(route, options).each_with_object([]) do |(param, value), memo|
180
180
  next if hidden_parameter?(value)
181
181
 
@@ -187,7 +187,7 @@ module Grape
187
187
  elsif value[:type]
188
188
  expose_params(value[:type])
189
189
  end
190
- memo << GrapeSwagger::DocMethods::ParseParams.call(param, value, path, route, @definitions)
190
+ memo << GrapeSwagger::DocMethods::ParseParams.call(param, value, path, route, @definitions, consumes)
191
191
  end
192
192
 
193
193
  if GrapeSwagger::DocMethods::MoveParams.can_be_moved?(route.request_method, parameters)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GrapeSwagger
4
- VERSION = '2.0.3'
4
+ VERSION = '2.1.0'
5
5
  end
data/lib/grape-swagger.rb CHANGED
@@ -24,7 +24,7 @@ module SwaggerRouting
24
24
  private
25
25
 
26
26
  def combine_routes(app, doc_klass)
27
- app.routes.each do |route|
27
+ app.routes.each_with_object({}) do |route, combined_routes|
28
28
  route_path = route.path
29
29
  route_match = route_path.split(/^.*?#{route.prefix}/).last
30
30
  next unless route_match
@@ -37,16 +37,16 @@ module SwaggerRouting
37
37
 
38
38
  resource = route_match.captures.first
39
39
  resource = '/' if resource.empty?
40
- @target_class.combined_routes[resource] ||= []
40
+ combined_routes[resource] ||= []
41
41
  next if doc_klass.hide_documentation_path && route.path.match(/#{doc_klass.mount_path}($|\/|\(\.)/)
42
42
 
43
- @target_class.combined_routes[resource] << route
43
+ combined_routes[resource] << route
44
44
  end
45
45
  end
46
46
 
47
- def determine_namespaced_routes(name, parent_route)
47
+ def determine_namespaced_routes(name, parent_route, routes)
48
48
  if parent_route.nil?
49
- @target_class.combined_routes.values.flatten
49
+ routes.values.flatten
50
50
  else
51
51
  parent_route.reject do |route|
52
52
  !route_path_start_with?(route, name) || !route_instance_variable_equals?(route, name)
@@ -54,14 +54,15 @@ module SwaggerRouting
54
54
  end
55
55
  end
56
56
 
57
- def combine_namespace_routes(namespaces)
57
+ def combine_namespace_routes(namespaces, routes)
58
+ combined_namespace_routes = {}
58
59
  # iterate over each single namespace
59
60
  namespaces.each_key do |name, _|
60
61
  # get the parent route for the namespace
61
62
  parent_route_name = extract_parent_route(name)
62
- parent_route = @target_class.combined_routes[parent_route_name]
63
+ parent_route = routes[parent_route_name]
63
64
  # fetch all routes that are within the current namespace
64
- namespace_routes = determine_namespaced_routes(name, parent_route)
65
+ namespace_routes = determine_namespaced_routes(name, parent_route, routes)
65
66
 
66
67
  # default case when not explicitly specified or nested == true
67
68
  standalone_namespaces = namespaces.reject do |_, ns|
@@ -76,12 +77,13 @@ module SwaggerRouting
76
77
  # rubocop:disable Style/Next
77
78
  if parent_standalone_namespaces.empty?
78
79
  # default option, append namespace methods to parent route
79
- parent_route = @target_class.combined_namespace_routes.key?(parent_route_name)
80
- @target_class.combined_namespace_routes[parent_route_name] = [] unless parent_route
81
- @target_class.combined_namespace_routes[parent_route_name].push(*namespace_routes)
80
+ combined_namespace_routes[parent_route_name] ||= []
81
+ combined_namespace_routes[parent_route_name].push(*namespace_routes)
82
82
  end
83
83
  # rubocop:enable Style/Next
84
84
  end
85
+
86
+ combined_namespace_routes
85
87
  end
86
88
 
87
89
  def extract_parent_route(name)
@@ -110,7 +112,7 @@ module SwaggerRouting
110
112
  end
111
113
 
112
114
  module SwaggerDocumentationAdder
113
- attr_accessor :combined_namespaces, :combined_namespace_identifiers, :combined_routes, :combined_namespace_routes
115
+ attr_accessor :combined_namespaces, :combined_routes, :combined_namespace_routes
114
116
 
115
117
  include SwaggerRouting
116
118
 
@@ -127,20 +129,16 @@ module SwaggerDocumentationAdder
127
129
  documentation_class.setup(options)
128
130
  mount(documentation_class)
129
131
 
130
- @target_class.combined_routes = {}
131
- combine_routes(@target_class, documentation_class)
132
-
133
- @target_class.combined_namespaces = {}
134
- combine_namespaces(@target_class)
132
+ combined_routes = combine_routes(@target_class, documentation_class)
133
+ combined_namespaces = combine_namespaces(@target_class)
134
+ combined_namespace_routes = combine_namespace_routes(combined_namespaces, combined_routes)
135
+ exclusive_route_keys = combined_routes.keys - combined_namespaces.keys
136
+ @target_class.combined_namespace_routes = combined_namespace_routes.merge(
137
+ combined_routes.slice(*exclusive_route_keys)
138
+ )
139
+ @target_class.combined_routes = combined_routes
140
+ @target_class.combined_namespaces = combined_namespaces
135
141
 
136
- @target_class.combined_namespace_routes = {}
137
- @target_class.combined_namespace_identifiers = {}
138
- combine_namespace_routes(@target_class.combined_namespaces)
139
-
140
- exclusive_route_keys = @target_class.combined_routes.keys - @target_class.combined_namespaces.keys
141
- exclusive_route_keys.each do |key|
142
- @target_class.combined_namespace_routes[key] = @target_class.combined_routes[key]
143
- end
144
142
  documentation_class
145
143
  end
146
144
 
@@ -151,17 +149,24 @@ module SwaggerDocumentationAdder
151
149
  end
152
150
 
153
151
  def combine_namespaces(app)
154
- app.endpoints.each do |endpoint|
152
+ combined_namespaces = {}
153
+ endpoints = app.endpoints.clone
154
+
155
+ while endpoints.any?
156
+ endpoint = endpoints.shift
157
+
158
+ endpoints.push(*endpoint.options[:app].endpoints) if endpoint.options[:app]
155
159
  ns = endpoint.namespace_stackable(:namespace).last
160
+ next unless ns
156
161
 
157
162
  # use the full namespace here (not the latest level only)
158
163
  # and strip leading slash
159
164
  mount_path = (endpoint.namespace_stackable(:mount_path) || []).join('/')
160
165
  full_namespace = (mount_path + endpoint.namespace).sub(/\/{2,}/, '/').sub(/^\//, '')
161
- @target_class.combined_namespaces[full_namespace] = ns if ns
162
-
163
- combine_namespaces(endpoint.options[:app]) if endpoint.options[:app]
166
+ combined_namespaces[full_namespace] = ns
164
167
  end
168
+
169
+ combined_namespaces
165
170
  end
166
171
 
167
172
  def create_documentation_class
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape-swagger
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.3
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - LeFnord
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-04-26 00:00:00.000000000 Z
12
+ date: 2024-05-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: grape