grape-swagger 2.0.3 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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