grape-swagger 0.10.1 → 0.10.2

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/RELEASING.md CHANGED
@@ -11,7 +11,7 @@ bundle install
11
11
  rake
12
12
  ```
13
13
 
14
- Check that the last build succeeded in [Travis CI](https://travis-ci.org/tim-vandecasteele/grape-swagger) for all supported platforms.
14
+ Check that the last build succeeded in [Travis CI](https://travis-ci.org/ruby-grape/grape-swagger) for all supported platforms.
15
15
 
16
16
  Increment the version, modify [lib/grape-swagger/version.rb](lib/grape-swagger/version.rb).
17
17
 
data/UPGRADING.md CHANGED
@@ -1,11 +1,28 @@
1
1
  Upgrading Grape-swagger
2
2
  =======================
3
3
 
4
+ ### Upgrading to >= 0.10.2
5
+
6
+ With grape >= 0.12.0, support for `notes` is replaced by passing a block `detail` option specified. For future compatibility, update your code:
7
+
8
+ ```ruby
9
+ desc 'Get all kittens!', notes: 'this will expose all the kittens'
10
+ ```
11
+
12
+ to
13
+
14
+ ``` ruby
15
+ desc 'Get all kittens!' do
16
+ detail 'this will expose all the kittens'
17
+ end
18
+ ```
19
+ Be aware of https://github.com/ruby-grape/grape/issues/920, currently grape accepts either an option hash OR a block for `desc`.
20
+
4
21
  ### Upgrading to >= 0.9.0
5
22
 
6
23
  #### Grape-Swagger-Rails
7
24
 
8
- If you're using [grape-swagger-rails](https://github.com/BrandyMint/grape-swagger-rails), remove the `.json` extension from `GrapeSwaggerRails.options.url`.
25
+ If you're using [grape-swagger-rails](https://github.com/ruby-grape/grape-swagger-rails), remove the `.json` extension from `GrapeSwaggerRails.options.url`.
9
26
 
10
27
  For example, change
11
28
 
@@ -19,7 +36,7 @@ to
19
36
  GrapeSwaggerRails.options.url = '/api/v1/swagger_doc'
20
37
  ```
21
38
 
22
- See [#187](https://github.com/tim-vandecasteele/grape-swagger/issues/187) for more information.
39
+ See [#187](https://github.com/ruby-grape/grape-swagger/issues/187) for more information.
23
40
 
24
41
  #### Grape 0.10.0
25
42
 
@@ -68,4 +85,4 @@ add_swagger_documentation (
68
85
  )
69
86
  ```
70
87
 
71
- See [#142](https://github.com/tim-vandecasteele/grape-swagger/pull/142) and documentation section [Markdown in Notes](https://github.com/tim-vandecasteele/grape-swagger#markdown-in-notes) for more information.
88
+ See [#142](https://github.com/ruby-grape/grape-swagger/pull/142) and documentation section [Markdown in Notes](https://github.com/ruby-grape/grape-swagger#markdown-in-notes) for more information.
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
7
7
  s.platform = Gem::Platform::RUBY
8
8
  s.authors = ['Tim Vandecasteele']
9
9
  s.email = ['tim.vandecasteele@gmail.com']
10
- s.homepage = 'https://github.com/tim-vandecasteele/grape-swagger'
10
+ s.homepage = 'https://github.com/ruby-grape/grape-swagger'
11
11
  s.summary = 'A simple way to add auto generated documentation to your Grape API that can be displayed with Swagger.'
12
12
  s.license = 'MIT'
13
13
 
data/lib/grape-swagger.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'grape'
2
2
  require 'grape-swagger/version'
3
3
  require 'grape-swagger/errors'
4
+ require 'grape-swagger/doc_methods'
4
5
  require 'grape-swagger/markdown'
5
6
  require 'grape-swagger/markdown/kramdown_adapter'
6
7
  require 'grape-swagger/markdown/redcarpet_adapter'
@@ -8,16 +9,19 @@ require 'grape-swagger/markdown/redcarpet_adapter'
8
9
  module Grape
9
10
  class API
10
11
  class << self
11
- attr_reader :combined_routes, :combined_namespaces, :combined_namespace_routes, :combined_namespace_identifiers
12
+ attr_accessor :combined_routes, :combined_namespaces, :combined_namespace_routes, :combined_namespace_identifiers
12
13
 
13
14
  def add_swagger_documentation(options = {})
14
15
  documentation_class = create_documentation_class
15
16
 
16
- documentation_class.setup({ target_class: self }.merge(options))
17
+ options = { target_class: self }.merge(options)
18
+ @target_class = options[:target_class]
19
+
20
+ documentation_class.setup(options)
17
21
  mount(documentation_class)
18
22
 
19
- @combined_routes = {}
20
- routes.each do |route|
23
+ @target_class.combined_routes = {}
24
+ @target_class.routes.each do |route|
21
25
  route_path = route.route_path
22
26
  route_match = route_path.split(/^.*?#{route.route_prefix.to_s}/).last
23
27
  next unless route_match
@@ -26,20 +30,20 @@ module Grape
26
30
  resource = route_match.captures.first
27
31
  next if resource.empty?
28
32
  resource.downcase!
29
- @combined_routes[resource] ||= []
30
- next if documentation_class.hide_documentation_path && route.route_path.include?(documentation_class.mount_path)
31
- @combined_routes[resource] << route
33
+ @target_class.combined_routes[resource] ||= []
34
+ next if documentation_class.hide_documentation_path && route.route_path.match(/#{documentation_class.mount_path}($|\/|\(\.)/)
35
+ @target_class.combined_routes[resource] << route
32
36
  end
33
37
 
34
- @combined_namespaces = {}
35
- combine_namespaces(self)
38
+ @target_class.combined_namespaces = {}
39
+ combine_namespaces(@target_class)
36
40
 
37
- @combined_namespace_routes = {}
38
- @combined_namespace_identifiers = {}
39
- combine_namespace_routes(@combined_namespaces)
41
+ @target_class.combined_namespace_routes = {}
42
+ @target_class.combined_namespace_identifiers = {}
43
+ combine_namespace_routes(@target_class.combined_namespaces)
40
44
 
41
- exclusive_route_keys = @combined_routes.keys - @combined_namespaces.keys
42
- exclusive_route_keys.each { |key| @combined_namespace_routes[key] = @combined_routes[key] }
45
+ exclusive_route_keys = @target_class.combined_routes.keys - @target_class.combined_namespaces.keys
46
+ exclusive_route_keys.each { |key| @target_class.combined_namespace_routes[key] = @target_class.combined_routes[key] }
43
47
  documentation_class
44
48
  end
45
49
 
@@ -54,7 +58,7 @@ module Grape
54
58
  end
55
59
  # use the full namespace here (not the latest level only)
56
60
  # and strip leading slash
57
- @combined_namespaces[endpoint.namespace.sub(/^\//, '')] = ns if ns
61
+ @target_class.combined_namespaces[endpoint.namespace.sub(/^\//, '')] = ns if ns
58
62
 
59
63
  combine_namespaces(endpoint.options[:app]) if endpoint.options[:app]
60
64
  end
@@ -65,7 +69,7 @@ module Grape
65
69
  namespaces.each do |name, namespace|
66
70
  # get the parent route for the namespace
67
71
  parent_route_name = name.match(%r{^/?([^/]*).*$})[1]
68
- parent_route = @combined_routes[parent_route_name]
72
+ parent_route = @target_class.combined_routes[parent_route_name]
69
73
  # fetch all routes that are within the current namespace
70
74
  namespace_routes = parent_route.collect do |route|
71
75
  route if (route.route_path.start_with?(route.route_prefix ? "/#{route.route_prefix}/#{name}" : "/#{name}") || route.route_path.start_with?((route.route_prefix ? "/#{route.route_prefix}/:version/#{name}" : "/:version/#{name}"))) &&
@@ -79,8 +83,8 @@ module Grape
79
83
  else
80
84
  identifier = name.gsub(/_/, '-').gsub(/\//, '_')
81
85
  end
82
- @combined_namespace_identifiers[identifier] = name
83
- @combined_namespace_routes[identifier] = namespace_routes
86
+ @target_class.combined_namespace_identifiers[identifier] = name
87
+ @target_class.combined_namespace_routes[identifier] = namespace_routes
84
88
 
85
89
  # get all nested namespaces below the current namespace
86
90
  sub_namespaces = standalone_sub_namespaces(name, namespaces)
@@ -92,7 +96,7 @@ module Grape
92
96
  route if sub_ns_paths.include?(route.instance_variable_get(:@options)[:namespace]) || sub_ns_paths_versioned.include?(route.instance_variable_get(:@options)[:namespace])
93
97
  end.compact
94
98
  # add all determined routes of the sub namespaces to standalone resource
95
- @combined_namespace_routes[identifier].push(*sub_routes)
99
+ @target_class.combined_namespace_routes[identifier].push(*sub_routes)
96
100
  else
97
101
  # default case when not explicitly specified or nested == true
98
102
  standalone_namespaces = namespaces.reject { |_, ns| !ns.options.key?(:swagger) || !ns.options[:swagger].key?(:nested) || ns.options[:swagger][:nested] != false }
@@ -100,8 +104,8 @@ module Grape
100
104
  # add only to the main route if the namespace is not within any other namespace appearing as standalone resource
101
105
  if parent_standalone_namespaces.empty?
102
106
  # default option, append namespace methods to parent route
103
- @combined_namespace_routes[parent_route_name] = [] unless @combined_namespace_routes.key?(parent_route_name)
104
- @combined_namespace_routes[parent_route_name].push(*namespace_routes)
107
+ @target_class.combined_namespace_routes[parent_route_name] = [] unless @target_class.combined_namespace_routes.key?(parent_route_name)
108
+ @target_class.combined_namespace_routes[parent_route_name].push(*namespace_routes)
105
109
  end
106
110
  end
107
111
  end
@@ -125,7 +129,7 @@ module Grape
125
129
 
126
130
  def get_non_nested_params(params)
127
131
  # Duplicate the params as we are going to modify them
128
- dup_params = params.each_with_object(Hash.new) do |(param, value), dparams|
132
+ dup_params = params.each_with_object({}) do |(param, value), dparams|
129
133
  dparams[param] = value.dup
130
134
  end
131
135
 
@@ -145,11 +149,13 @@ module Grape
145
149
  params.each_key do |k|
146
150
  if params[k].is_a?(Hash) && params[k][:type] == 'Array'
147
151
  array_param = k
152
+ modified_params[k] = params[k]
148
153
  else
149
154
  new_key = k
150
155
  unless array_param.nil?
151
156
  if k.to_s.start_with?(array_param.to_s + '[')
152
157
  new_key = array_param.to_s + '[]' + k.to_s.split(array_param)[1]
158
+ modified_params.delete array_param
153
159
  end
154
160
  end
155
161
  modified_params[new_key] = params[k]
@@ -158,462 +164,29 @@ module Grape
158
164
  modified_params
159
165
  end
160
166
 
161
- def create_documentation_class
162
- Class.new(Grape::API) do
163
- class << self
164
- def name
165
- @@class_name
166
- end
167
-
168
- def as_markdown(description)
169
- description && @@markdown ? @@markdown.as_markdown(strip_heredoc(description)) : description
170
- end
171
-
172
- def parse_params(params, path, method)
173
- params ||= []
174
-
175
- parsed_array_params = parse_array_params(params)
176
-
177
- non_nested_parent_params = get_non_nested_params(parsed_array_params)
178
-
179
- non_nested_parent_params.map do |param, value|
180
- items = {}
181
-
182
- raw_data_type = value.is_a?(Hash) ? (value[:type] || 'string').to_s : 'string'
183
- data_type = case raw_data_type
184
- when 'Hash'
185
- 'object'
186
- when 'Rack::Multipart::UploadedFile'
187
- 'File'
188
- when 'Virtus::Attribute::Boolean'
189
- 'boolean'
190
- when 'Boolean', 'Date', 'Integer', 'String', 'Float'
191
- raw_data_type.downcase
192
- when 'BigDecimal'
193
- 'long'
194
- when 'DateTime'
195
- 'dateTime'
196
- when 'Numeric'
197
- 'double'
198
- when 'Symbol'
199
- 'string'
200
- else
201
- @@documentation_class.parse_entity_name(raw_data_type)
202
- end
203
- description = value.is_a?(Hash) ? value[:desc] || value[:description] : ''
204
- required = value.is_a?(Hash) ? !!value[:required] : false
205
- default_value = value.is_a?(Hash) ? value[:default] : nil
206
- is_array = value.is_a?(Hash) ? (value[:is_array] || false) : false
207
- enum_values = value.is_a?(Hash) ? value[:values] : nil
208
- enum_values = enum_values.to_a if enum_values && enum_values.is_a?(Range)
209
- enum_values = enum_values.call if enum_values && enum_values.is_a?(Proc)
210
-
211
- if value.is_a?(Hash) && value.key?(:param_type)
212
- param_type = value[:param_type]
213
- if is_array
214
- items = { '$ref' => data_type }
215
- data_type = 'array'
216
- end
217
- else
218
- param_type = case
219
- when path.include?(":#{param}")
220
- 'path'
221
- when %w(POST PUT PATCH).include?(method)
222
- if is_primitive?(data_type)
223
- 'form'
224
- else
225
- 'body'
226
- end
227
- else
228
- 'query'
229
- end
230
- end
231
- name = (value.is_a?(Hash) && value[:full_name]) || param
232
-
233
- parsed_params = {
234
- paramType: param_type,
235
- name: name,
236
- description: as_markdown(description),
237
- type: data_type,
238
- required: required,
239
- allowMultiple: is_array
240
- }
241
- parsed_params.merge!(format: 'int32') if data_type == 'integer'
242
- parsed_params.merge!(format: 'int64') if data_type == 'long'
243
- parsed_params.merge!(items: items) if items.present?
244
- parsed_params.merge!(defaultValue: default_value) if default_value
245
- parsed_params.merge!(enum: enum_values) if enum_values
246
- parsed_params
247
- end
248
- end
249
-
250
- def content_types_for(target_class)
251
- content_types = (target_class.content_types || {}).values
252
-
253
- if content_types.empty?
254
- formats = [target_class.format, target_class.default_format].compact.uniq
255
- formats = Grape::Formatter::Base.formatters({}).keys if formats.empty?
256
- content_types = Grape::ContentTypes::CONTENT_TYPES.select { |content_type, _mime_type| formats.include? content_type }.values
257
- end
258
-
259
- content_types.uniq
260
- end
261
-
262
- def parse_info(info)
263
- {
264
- contact: info[:contact],
265
- description: as_markdown(info[:description]),
266
- license: info[:license],
267
- licenseUrl: info[:license_url],
268
- termsOfServiceUrl: info[:terms_of_service_url],
269
- title: info[:title]
270
- }.delete_if { |_, value| value.blank? }
271
- end
272
-
273
- def parse_header_params(params)
274
- params ||= []
275
-
276
- params.map do |param, value|
277
- data_type = 'String'
278
- description = value.is_a?(Hash) ? value[:description] : ''
279
- required = value.is_a?(Hash) ? !!value[:required] : false
280
- default_value = value.is_a?(Hash) ? value[:default] : nil
281
- param_type = 'header'
282
-
283
- parsed_params = {
284
- paramType: param_type,
285
- name: param,
286
- description: as_markdown(description),
287
- type: data_type,
288
- required: required
289
- }
290
-
291
- parsed_params.merge!(defaultValue: default_value) if default_value
292
-
293
- parsed_params
294
- end
295
- end
296
-
297
- def parse_path(path, version)
298
- # adapt format to swagger format
299
- parsed_path = path.gsub('(.:format)', @@hide_format ? '' : '.{format}')
300
- # This is attempting to emulate the behavior of
301
- # Rack::Mount::Strexp. We cannot use Strexp directly because
302
- # all it does is generate regular expressions for parsing URLs.
303
- # TODO: Implement a Racc tokenizer to properly generate the
304
- # parsed path.
305
- parsed_path = parsed_path.gsub(/:([a-zA-Z_]\w*)/, '{\1}')
306
- # add the version
307
- version ? parsed_path.gsub('{version}', version) : parsed_path
308
- end
309
-
310
- def parse_entity_name(model)
311
- if model.respond_to?(:entity_name)
312
- model.entity_name
313
- else
314
- name = model.to_s
315
- entity_parts = name.split('::')
316
- entity_parts.reject! { |p| p == 'Entity' || p == 'Entities' }
317
- entity_parts.join('::')
318
- end
319
- end
320
-
321
- def parse_entity_models(models)
322
- result = {}
323
- models.each do |model|
324
- name = parse_entity_name(model)
325
- properties = {}
326
- required = []
327
-
328
- model.documentation.each do |property_name, property_info|
329
- p = property_info.dup
330
-
331
- required << property_name.to_s if p.delete(:required)
332
-
333
- type = if p[:type]
334
- p.delete(:type)
335
- else
336
- exposure = model.exposures[property_name]
337
- parse_entity_name(exposure[:using]) if exposure
338
- end
339
-
340
- if p.delete(:is_array)
341
- p[:items] = generate_typeref(type)
342
- p[:type] = 'array'
343
- else
344
- p.merge! generate_typeref(type)
345
- end
346
-
347
- # rename Grape Entity's "desc" to "description"
348
- property_description = p.delete(:desc)
349
- p[:description] = property_description if property_description
350
-
351
- # rename Grape's 'values' to 'enum'
352
- select_values = p.delete(:values)
353
- if select_values
354
- select_values = select_values.call if select_values.is_a?(Proc)
355
- p[:enum] = select_values
356
- end
357
-
358
- properties[property_name] = p
359
- end
360
-
361
- result[name] = {
362
- id: model.instance_variable_get(:@root) || name,
363
- properties: properties
364
- }
365
- result[name].merge!(required: required) unless required.empty?
366
- end
367
-
368
- result
369
- end
370
-
371
- def models_with_included_presenters(models)
372
- all_models = models
373
-
374
- models.each do |model|
375
- # get model references from exposures with a documentation
376
- nested_models = model.exposures.map do |_, config|
377
- if config.key?(:documentation)
378
- model = config[:using]
379
- model.respond_to?(:constantize) ? model.constantize : model
380
- end
381
- end.compact
382
-
383
- # get all nested models recursively
384
- additional_models = nested_models.map do |nested_model|
385
- models_with_included_presenters([nested_model])
386
- end.flatten
387
-
388
- all_models += additional_models
389
- end
390
-
391
- all_models
392
- end
393
-
394
- def is_primitive?(type)
395
- %w(object integer long float double string byte boolean date dateTime).include? type
396
- end
397
-
398
- def generate_typeref(type)
399
- type = type.to_s.sub(/^[A-Z]/) { |f| f.downcase } if type.is_a?(Class)
400
- if is_primitive? type
401
- { 'type' => type }
402
- else
403
- { '$ref' => type }
404
- end
405
- end
406
-
407
- def parse_http_codes(codes, models)
408
- codes ||= {}
409
- codes.map do |k, v, m|
410
- models << m if m
411
- http_code_hash = {
412
- code: k,
413
- message: v
414
- }
415
- http_code_hash[:responseModel] = parse_entity_name(m) if m
416
- http_code_hash
417
- end
418
- end
419
-
420
- def strip_heredoc(string)
421
- indent = string.scan(/^[ \t]*(?=\S)/).min.try(:size) || 0
422
- string.gsub(/^[ \t]{#{indent}}/, '')
423
- end
424
-
425
- def parse_base_path(base_path, request)
426
- if base_path.is_a?(Proc)
427
- base_path.call(request)
428
- elsif base_path.is_a?(String)
429
- URI(base_path).relative? ? URI.join(request.base_url, base_path).to_s : base_path
430
- else
431
- request.base_url
432
- end
433
- end
434
-
435
- def hide_documentation_path
436
- @@hide_documentation_path
437
- end
438
-
439
- def mount_path
440
- @@mount_path
441
- end
442
-
443
- def setup(options)
444
- defaults = {
445
- target_class: nil,
446
- mount_path: '/swagger_doc',
447
- base_path: nil,
448
- api_version: '0.1',
449
- markdown: nil,
450
- hide_documentation_path: false,
451
- hide_format: false,
452
- format: nil,
453
- models: [],
454
- info: {},
455
- authorizations: nil,
456
- root_base_path: true,
457
- api_documentation: { desc: 'Swagger compatible API description' },
458
- specific_api_documentation: { desc: 'Swagger compatible API description for specific API' }
459
- }
460
-
461
- options = defaults.merge(options)
462
-
463
- target_class = options[:target_class]
464
- @@mount_path = options[:mount_path]
465
- @@class_name = options[:class_name] || options[:mount_path].gsub('/', '')
466
- @@markdown = options[:markdown] ? GrapeSwagger::Markdown.new(options[:markdown]) : nil
467
- @@hide_format = options[:hide_format]
468
- api_version = options[:api_version]
469
- authorizations = options[:authorizations]
470
- root_base_path = options[:root_base_path]
471
- extra_info = options[:info]
472
- api_doc = options[:api_documentation].dup
473
- specific_api_doc = options[:specific_api_documentation].dup
474
- @@models = options[:models] || []
475
-
476
- @@hide_documentation_path = options[:hide_documentation_path]
477
-
478
- if options[:format]
479
- [:format, :default_format, :default_error_formatter].each do |method|
480
- send(method, options[:format])
481
- end
482
- end
483
-
484
- @@documentation_class = self
485
-
486
- desc api_doc.delete(:desc), api_doc
487
- get @@mount_path do
488
- header['Access-Control-Allow-Origin'] = '*'
489
- header['Access-Control-Request-Method'] = '*'
490
-
491
- namespaces = target_class.combined_namespaces
492
- namespace_routes = target_class.combined_namespace_routes
493
-
494
- if @@hide_documentation_path
495
- namespace_routes.reject! { |route, _value| "/#{route}/".index(@@documentation_class.parse_path(@@mount_path, nil) << '/') == 0 }
496
- end
497
-
498
- namespace_routes_array = namespace_routes.keys.map do |local_route|
499
- next if namespace_routes[local_route].map(&:route_hidden).all? { |value| value.respond_to?(:call) ? value.call : value }
500
-
501
- url_format = '.{format}' unless @@hide_format
502
-
503
- original_namespace_name = target_class.combined_namespace_identifiers.key?(local_route) ? target_class.combined_namespace_identifiers[local_route] : local_route
504
- description = namespaces[original_namespace_name] && namespaces[original_namespace_name].options[:desc]
505
- description ||= "Operations about #{original_namespace_name.pluralize}"
506
-
507
- {
508
- path: "/#{local_route}#{url_format}",
509
- description: description
510
- }
511
- end.compact
512
-
513
- output = {
514
- apiVersion: api_version,
515
- swaggerVersion: '1.2',
516
- produces: @@documentation_class.content_types_for(target_class),
517
- apis: namespace_routes_array,
518
- info: @@documentation_class.parse_info(extra_info)
519
- }
520
-
521
- output[:authorizations] = authorizations unless authorizations.nil? || authorizations.empty?
522
-
523
- output
524
- end
525
-
526
- desc specific_api_doc.delete(:desc), { params: {
527
- 'name' => {
528
- desc: 'Resource name of mounted API',
529
- type: 'string',
530
- required: true
531
- }
532
- }.merge(specific_api_doc.delete(:params) || {}) }.merge(specific_api_doc)
533
-
534
- get "#{@@mount_path}/:name" do
535
- header['Access-Control-Allow-Origin'] = '*'
536
- header['Access-Control-Request-Method'] = '*'
537
-
538
- models = []
539
- routes = target_class.combined_namespace_routes[params[:name]]
540
- error!('Not Found', 404) unless routes
541
-
542
- visible_ops = routes.reject do |route|
543
- route.route_hidden.respond_to?(:call) ? route.route_hidden.call : route.route_hidden
544
- end
545
-
546
- ops = visible_ops.group_by do |route|
547
- @@documentation_class.parse_path(route.route_path, api_version)
548
- end
549
-
550
- error!('Not Found', 404) unless ops.any?
551
-
552
- apis = []
553
-
554
- ops.each do |path, op_routes|
555
- operations = op_routes.map do |route|
556
- notes = @@documentation_class.as_markdown(route.route_notes)
557
-
558
- http_codes = @@documentation_class.parse_http_codes(route.route_http_codes, models)
559
-
560
- models |= @@models if @@models.present?
561
-
562
- models |= Array(route.route_entity) if route.route_entity.present?
563
-
564
- models = @@documentation_class.models_with_included_presenters(models.flatten.compact)
565
-
566
- operation = {
567
- notes: notes.to_s,
568
- summary: route.route_description || '',
569
- nickname: route.route_nickname || (route.route_method + route.route_path.gsub(/[\/:\(\)\.]/, '-')),
570
- method: route.route_method,
571
- parameters: @@documentation_class.parse_header_params(route.route_headers) + @@documentation_class.parse_params(route.route_params, route.route_path, route.route_method),
572
- type: 'void'
573
- }
574
- operation[:authorizations] = route.route_authorizations unless route.route_authorizations.nil? || route.route_authorizations.empty?
575
- if operation[:parameters].any? { | param | param[:type] == 'File' }
576
- operation.merge!(consumes: ['multipart/form-data'])
577
- end
578
- operation.merge!(responseMessages: http_codes) unless http_codes.empty?
579
-
580
- if route.route_entity
581
- type = @@documentation_class.parse_entity_name(Array(route.route_entity).first)
582
- operation.merge!('type' => type)
583
- end
584
-
585
- operation[:nickname] = route.route_nickname if route.route_nickname
586
- operation
587
- end.compact
588
- apis << {
589
- path: path,
590
- operations: operations
591
- }
592
- end
593
-
594
- # use custom resource naming if available
595
- if target_class.combined_namespace_identifiers.key? params[:name]
596
- resource_path = target_class.combined_namespace_identifiers[params[:name]]
597
- else
598
- resource_path = params[:name]
599
- end
600
- api_description = {
601
- apiVersion: api_version,
602
- swaggerVersion: '1.2',
603
- resourcePath: "/#{resource_path}",
604
- produces: @@documentation_class.content_types_for(target_class),
605
- apis: apis
606
- }
167
+ def parse_enum_or_range_values(values)
168
+ case values
169
+ when Range
170
+ parse_range_values(values) if values.first.is_a?(Integer)
171
+ when Proc
172
+ values_result = values.call
173
+ if values_result.is_a?(Range) && values_result.first.is_a?(Integer)
174
+ parse_range_values(values_result)
175
+ else
176
+ { enum: values_result }
177
+ end
178
+ else
179
+ { enum: values } if values
180
+ end
181
+ end
607
182
 
608
- base_path = @@documentation_class.parse_base_path(options[:base_path], request)
609
- api_description[:basePath] = base_path if base_path && base_path.size > 0 && root_base_path != false
610
- api_description[:models] = @@documentation_class.parse_entity_models(models) unless models.empty?
611
- api_description[:authorizations] = authorizations if authorizations
183
+ def parse_range_values(values)
184
+ { minimum: values.first, maximum: values.last }
185
+ end
612
186
 
613
- api_description
614
- end
615
- end
616
- end
187
+ def create_documentation_class
188
+ Class.new(Grape::API) do
189
+ extend GrapeSwagger::DocMethods
617
190
  end
618
191
  end
619
192
  end