grape-swagger 0.10.1 → 0.10.2

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