grape-swagger 1.2.1 → 1.3.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: 8ced0e59624b64b14e517815c13c6761c970da13cfd7e6d5c82493b1bb49c815
4
- data.tar.gz: a5891f3a10dc5e3ae96bb1f295dcf1978f0758175160b1681ba5f85f0b7cc206
3
+ metadata.gz: 7a3f65f49a31d6affe69a657daff3867582070436163992acb47f1166dde1cc6
4
+ data.tar.gz: da9f13e2efd7e2b23dc92eea5b9deeaf4d9b8a860b13bae2b7f928b31d996be3
5
5
  SHA512:
6
- metadata.gz: 61c9297050672b095bf2ab8a6648420b6226fa5ecaa2b1b2df07e99c271dba4f1fe9547a77eae5dc4e1b5d0b29035f823e389957b57149f4fb79cf3187597ee9
7
- data.tar.gz: 55f926c09f83bfe6e0ab15caeac329acf6f6d623d9c579b89c872fdd2f11f5ddece4e0a74259f921688bcf8e2255fecd908fce3f2eb4b2b58ed449803d3c2900
6
+ metadata.gz: 0d51d5cde5ff558fefcbf8b4503d290bc535c48f22d1ee3c2662ad406c548b7ef72d196b36598b2d3ea68d6ebef8e6ce43e3dec8dab6f371df9d12aaadd34567
7
+ data.tar.gz: b22301456da8cd150767fd614434bfad161959eb0836b028b4ff8d15893fd128c53513e87ab8180a6442b8fda9ec41a6e6648b67cb32a46b692d2b117e229ec1
@@ -4,6 +4,7 @@ AllCops:
4
4
  Exclude:
5
5
  - vendor/**/*
6
6
  - example/**/*
7
+ NewCops: enable
7
8
  TargetRubyVersion: 2.7
8
9
 
9
10
  # Layout stuff
@@ -80,8 +81,12 @@ Style/CaseLikeIf:
80
81
  Style/ExponentialNotation:
81
82
  Enabled: true
82
83
 
84
+ Style/ExplicitBlockArgument:
85
+ Enabled: false
86
+
83
87
  Style/HashAsLastArrayItem:
84
88
  Enabled: true
89
+
85
90
  Style/HashEachMethods:
86
91
  Enabled: true
87
92
 
@@ -114,5 +119,3 @@ Style/RedundantRegexpEscape:
114
119
 
115
120
  Style/SlicingWithRange:
116
121
  Enabled: false
117
-
118
-
@@ -29,8 +29,12 @@ jobs:
29
29
  env:
30
30
  - rvm: jruby-head
31
31
  env:
32
+ - rvm: truffleruby-head
33
+ env:
34
+ script: bundle exec rake spec
32
35
 
33
36
  allow_failures:
34
37
  - rvm: 2.4.10
35
38
  - rvm: ruby-head
36
39
  - rvm: jruby-head
40
+ - rvm: truffleruby-head
@@ -9,6 +9,13 @@
9
9
  * Your contribution here.
10
10
 
11
11
 
12
+ ### 1.3.0 (September 3, 2020)
13
+
14
+ #### Features
15
+
16
+ * [#804](https://github.com/ruby-grape/grape-swagger/pull/804): Don't overwrite model description with the route description - [@Bhacaz](https://github.com/Bhacaz).
17
+
18
+
12
19
  ### 1.2.1 (July 15, 2020)
13
20
 
14
21
  #### Fixes
data/Gemfile CHANGED
@@ -27,7 +27,7 @@ group :development, :test do
27
27
  gem 'rake'
28
28
  gem 'rdoc'
29
29
  gem 'rspec', '~> 3.9'
30
- gem 'rubocop', '~> 0.88', require: false
30
+ gem 'rubocop', '~> 0.90', require: false
31
31
  end
32
32
 
33
33
  group :test do
data/README.md CHANGED
@@ -859,10 +859,11 @@ get '/thing', failure: [
859
859
  end
860
860
  ```
861
861
 
862
- By adding a `model` key, e.g. this would be taken.
862
+ By adding a `model` key, e.g. this would be taken. Setting an empty string will act like an empty body.
863
863
  ```ruby
864
864
  get '/thing', failure: [
865
865
  { code: 400, message: 'General error' },
866
+ { code: 403, message: 'Forbidden error', model: '' },
866
867
  { code: 422, message: 'Invalid parameter entry', model: Entities::ApiError }
867
868
  ] do
868
869
  # ...
@@ -1,5 +1,9 @@
1
1
  ## Upgrading Grape-swagger
2
2
 
3
+ ### Upgrading to >= 1.3.0
4
+
5
+ - The model (entity) description no longer comes from the route description. It will have a default value: `<<EntityName>> model`.
6
+
3
7
  ### Upgrading to >= 1.2.0
4
8
 
5
9
  - The entity_name class method is now called on parent classes for inherited entities. Now you can do this
@@ -17,6 +17,61 @@ require 'grape-swagger/doc_methods/version'
17
17
 
18
18
  module GrapeSwagger
19
19
  module DocMethods
20
+ DEFAULTS =
21
+ {
22
+ info: {},
23
+ models: [],
24
+ doc_version: '0.0.1',
25
+ target_class: nil,
26
+ mount_path: '/swagger_doc',
27
+ host: nil,
28
+ base_path: nil,
29
+ add_base_path: false,
30
+ add_version: true,
31
+ add_root: false,
32
+ hide_documentation_path: true,
33
+ format: :json,
34
+ authorizations: nil,
35
+ security_definitions: nil,
36
+ security: nil,
37
+ api_documentation: { desc: 'Swagger compatible API description' },
38
+ specific_api_documentation: { desc: 'Swagger compatible API description for specific API' },
39
+ endpoint_auth_wrapper: nil,
40
+ swagger_endpoint_guard: nil,
41
+ token_owner: nil
42
+ }.freeze
43
+
44
+ FORMATTER_METHOD = %i[format default_format default_error_formatter].freeze
45
+
46
+ def self.output_path_definitions(combi_routes, endpoint, target_class, options)
47
+ output = endpoint.swagger_object(
48
+ target_class,
49
+ endpoint.request,
50
+ options
51
+ )
52
+
53
+ paths, definitions = endpoint.path_and_definition_objects(combi_routes, options)
54
+ tags = tags_from(paths, options)
55
+
56
+ output[:tags] = tags unless tags.empty? || paths.blank?
57
+ output[:paths] = paths unless paths.blank?
58
+ output[:definitions] = definitions unless definitions.blank?
59
+
60
+ output
61
+ end
62
+
63
+ def self.tags_from(paths, options)
64
+ tags = GrapeSwagger::DocMethods::TagNameDescription.build(paths)
65
+
66
+ if options[:tags]
67
+ names = options[:tags].map { |t| t[:name] }
68
+ tags.reject! { |t| names.include?(t[:name]) }
69
+ tags += options[:tags]
70
+ end
71
+
72
+ tags
73
+ end
74
+
20
75
  def hide_documentation_path
21
76
  @@hide_documentation_path
22
77
  end
@@ -26,54 +81,32 @@ module GrapeSwagger
26
81
  end
27
82
 
28
83
  def setup(options)
29
- options = defaults.merge(options)
84
+ options = DEFAULTS.merge(options)
30
85
 
31
86
  # options could be set on #add_swagger_documentation call,
32
87
  # for available options see #defaults
33
88
  target_class = options[:target_class]
34
89
  guard = options[:swagger_endpoint_guard]
35
- formatter = options[:format]
36
90
  api_doc = options[:api_documentation].dup
37
91
  specific_api_doc = options[:specific_api_documentation].dup
38
92
 
39
93
  class_variables_from(options)
40
94
 
41
- if formatter
42
- %i[format default_format default_error_formatter].each do |method|
43
- send(method, formatter)
44
- end
45
- end
95
+ setup_formatter(options[:format])
46
96
 
47
97
  desc api_doc.delete(:desc), api_doc
48
98
 
49
- output_path_definitions = proc do |combi_routes, endpoint|
50
- output = endpoint.swagger_object(
51
- target_class,
52
- endpoint.request,
53
- options
54
- )
55
-
56
- paths, definitions = endpoint.path_and_definition_objects(combi_routes, options)
57
- tags = tags_from(paths, options)
58
-
59
- output[:tags] = tags unless tags.empty? || paths.blank?
60
- output[:paths] = paths unless paths.blank?
61
- output[:definitions] = definitions unless definitions.blank?
62
-
63
- output
64
- end
65
-
66
99
  instance_eval(guard) unless guard.nil?
67
100
 
68
101
  get mount_path do
69
102
  header['Access-Control-Allow-Origin'] = '*'
70
103
  header['Access-Control-Request-Method'] = '*'
71
104
 
72
- output_path_definitions.call(target_class.combined_namespace_routes, self)
105
+ GrapeSwagger::DocMethods
106
+ .output_path_definitions(target_class.combined_namespace_routes, self, target_class, options)
73
107
  end
74
108
 
75
- desc specific_api_doc.delete(:desc), { params:
76
- specific_api_doc.delete(:params) || {} }.merge(specific_api_doc)
109
+ desc specific_api_doc.delete(:desc), { params: specific_api_doc.delete(:params) || {}, **specific_api_doc }
77
110
 
78
111
  params do
79
112
  requires :name, type: String, desc: 'Resource name of mounted API'
@@ -88,51 +121,21 @@ module GrapeSwagger
88
121
  combined_routes = target_class.combined_namespace_routes[params[:name]]
89
122
  error!({ error: 'named resource not exist' }, 400) if combined_routes.nil?
90
123
 
91
- output_path_definitions.call({ params[:name] => combined_routes }, self)
124
+ GrapeSwagger::DocMethods
125
+ .output_path_definitions({ params[:name] => combined_routes }, self, target_class, options)
92
126
  end
93
127
  end
94
128
 
95
- def defaults
96
- {
97
- info: {},
98
- models: [],
99
- doc_version: '0.0.1',
100
- target_class: nil,
101
- mount_path: '/swagger_doc',
102
- host: nil,
103
- base_path: nil,
104
- add_base_path: false,
105
- add_version: true,
106
- add_root: false,
107
- hide_documentation_path: true,
108
- format: :json,
109
- authorizations: nil,
110
- security_definitions: nil,
111
- security: nil,
112
- api_documentation: { desc: 'Swagger compatible API description' },
113
- specific_api_documentation: { desc: 'Swagger compatible API description for specific API' },
114
- endpoint_auth_wrapper: nil,
115
- swagger_endpoint_guard: nil,
116
- token_owner: nil
117
- }
118
- end
119
-
120
129
  def class_variables_from(options)
121
130
  @@mount_path = options[:mount_path]
122
131
  @@class_name = options[:class_name] || options[:mount_path].delete('/')
123
132
  @@hide_documentation_path = options[:hide_documentation_path]
124
133
  end
125
134
 
126
- def tags_from(paths, options)
127
- tags = GrapeSwagger::DocMethods::TagNameDescription.build(paths)
135
+ def setup_formatter(formatter)
136
+ return unless formatter
128
137
 
129
- if options[:tags]
130
- names = options[:tags].map { |t| t[:name] }
131
- tags.reject! { |t| names.include?(t[:name]) }
132
- tags += options[:tags]
133
- end
134
-
135
- tags
138
+ FORMATTER_METHOD.each { |method| send(method, formatter) }
136
139
  end
137
140
  end
138
141
  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.include?(b[:name].to_s.gsub(/\[\]\z/, '') + '[')
10
+ p[:name] != b[:name] && p[:name].to_s.include?("#{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
@@ -30,7 +30,7 @@ module GrapeSwagger
30
30
 
31
31
  def add_braces(parameter, related_parameters)
32
32
  param_name = parameter[:name].gsub(/\A(.*)\[\]\z/, '\1')
33
- related_parameters.each { |p| p[:name] = p[:name].gsub(param_name, param_name + '[]') }
33
+ related_parameters.each { |p| p[:name] = p[:name].gsub(param_name, "#{param_name}[]") }
34
34
  end
35
35
 
36
36
  def add_array(parameter, related_parameters)
@@ -11,7 +11,7 @@ module Grape
11
11
 
12
12
  if content_types.empty?
13
13
  formats = [target_class.format, target_class.default_format].compact.uniq
14
- formats = Grape::Formatter.formatters({}).keys if formats.empty?
14
+ formats = Grape::Formatter.formatters(**{}).keys if formats.empty?
15
15
  content_types = Grape::ContentTypes::CONTENT_TYPES.select do |content_type, _mime_type|
16
16
  formats.include? content_type
17
17
  end.values
@@ -78,11 +78,11 @@ module Grape
78
78
  def path_and_definition_objects(namespace_routes, options)
79
79
  @paths = {}
80
80
  @definitions = {}
81
+ add_definitions_from options[:models]
81
82
  namespace_routes.each_value do |routes|
82
83
  path_item(routes, options)
83
84
  end
84
85
 
85
- add_definitions_from options[:models]
86
86
  [@paths, @definitions]
87
87
  end
88
88
 
@@ -207,19 +207,20 @@ module Grape
207
207
 
208
208
  next build_file_response(memo[value[:code]]) if file_response?(value[:model])
209
209
 
210
- response_model = @item
211
- response_model = expose_params_from_model(value[:model]) if value[:model]
212
-
213
210
  if memo.key?(200) && route.request_method == 'DELETE' && value[:model].nil?
214
211
  memo[204] = memo.delete(200)
215
212
  value[:code] = 204
213
+ next
216
214
  end
217
215
 
218
- next if value[:code] == 204
219
- next unless !response_model.start_with?('Swagger_doc') && (@definitions[response_model] || value[:model])
216
+ # Explicitly request no model with { model: '' }
217
+ next if value[:model] == ''
220
218
 
221
- @definitions[response_model][:description] = description_object(route)
219
+ response_model = value[:model] ? expose_params_from_model(value[:model]) : @item
220
+ next unless @definitions[response_model]
221
+ next if response_model.start_with?('Swagger_doc')
222
222
 
223
+ @definitions[response_model][:description] ||= "#{response_model} model"
223
224
  memo[value[:code]][:schema] = build_reference(route, value, response_model, options)
224
225
  memo[value[:code]][:examples] = value[:examples] if value[:examples]
225
226
  end
@@ -364,7 +365,7 @@ module Grape
364
365
  end
365
366
 
366
367
  def hidden_parameter?(value)
367
- return false if value.dig(:required)
368
+ return false if value[:required]
368
369
 
369
370
  if value.dig(:documentation, :hidden).is_a?(Proc)
370
371
  value.dig(:documentation, :hidden).call
@@ -74,6 +74,7 @@ module GrapeSwagger
74
74
 
75
75
  # helper methods
76
76
  #
77
+ # rubocop:disable Style/StringConcatenation
77
78
  def make_request
78
79
  get url_for
79
80
 
@@ -83,6 +84,7 @@ module GrapeSwagger
83
84
  )
84
85
  ) + "\n"
85
86
  end
87
+ # rubocop:enable Style/StringConcatenation
86
88
 
87
89
  def url_for
88
90
  oapi_route = api_class.routes[-2]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GrapeSwagger
4
- VERSION = '1.2.1'
4
+ VERSION = '1.3.0'
5
5
  end
@@ -97,7 +97,7 @@ describe GrapeSwagger::DocMethods::MoveParams do
97
97
  let(:route_options) { { requirements: {} } }
98
98
  describe 'POST' do
99
99
  let(:params) { paths[path][:post][:parameters] }
100
- let(:route) { Grape::Router::Route.new('POST', path.dup, route_options) }
100
+ let(:route) { Grape::Router::Route.new('POST', path.dup, **route_options) }
101
101
 
102
102
  specify do
103
103
  subject.to_definition(path, params, route, definitions)
@@ -113,7 +113,7 @@ describe GrapeSwagger::DocMethods::MoveParams do
113
113
 
114
114
  describe 'POST' do
115
115
  let(:params) { paths['/in_body/{key}'][:put][:parameters] }
116
- let(:route) { Grape::Router::Route.new('PUT', path.dup, route_options) }
116
+ let(:route) { Grape::Router::Route.new('PUT', path.dup, **route_options) }
117
117
 
118
118
  specify do
119
119
  subject.to_definition(path, params, route, definitions)
@@ -145,23 +145,23 @@ RSpec.shared_context 'entity swagger example' do
145
145
 
146
146
  let(:swagger_nested_type) do
147
147
  {
148
- 'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'type' => 'integer', 'format' => 'int32', 'description' => 'status code' }, 'message' => { 'type' => 'string', 'description' => 'error message' } }, 'description' => 'This returns something' },
148
+ 'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'type' => 'integer', 'format' => 'int32', 'description' => 'status code' }, 'message' => { 'type' => 'string', 'description' => 'error message' } }, 'description' => 'ApiError model' },
149
149
  'ResponseItem' => { 'type' => 'object', 'properties' => { 'id' => { 'type' => 'integer', 'format' => 'int32' }, 'name' => { 'type' => 'string' } } },
150
- 'UseItemResponseAsType' => { 'type' => 'object', 'properties' => { 'description' => { 'type' => 'string' }, 'responses' => { '$ref' => '#/definitions/ResponseItem' } }, 'description' => 'This returns something' }
150
+ 'UseItemResponseAsType' => { 'type' => 'object', 'properties' => { 'description' => { 'type' => 'string' }, 'responses' => { '$ref' => '#/definitions/ResponseItem' } }, 'description' => 'UseItemResponseAsType model' }
151
151
  }
152
152
  end
153
153
 
154
154
  let(:swagger_entity_as_response_object) do
155
155
  {
156
- 'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'type' => 'integer', 'format' => 'int32', 'description' => 'status code' }, 'message' => { 'type' => 'string', 'description' => 'error message' } }, 'description' => 'This returns something' },
156
+ 'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'type' => 'integer', 'format' => 'int32', 'description' => 'status code' }, 'message' => { 'type' => 'string', 'description' => 'error message' } }, 'description' => 'ApiError model' },
157
157
  'ResponseItem' => { 'type' => 'object', 'properties' => { 'id' => { 'type' => 'integer', 'format' => 'int32' }, 'name' => { 'type' => 'string' } } },
158
- 'UseResponse' => { 'type' => 'object', 'properties' => { 'description' => { 'type' => 'string' }, '$responses' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/ResponseItem' } } }, 'description' => 'This returns something' }
158
+ 'UseResponse' => { 'type' => 'object', 'properties' => { 'description' => { 'type' => 'string' }, '$responses' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/ResponseItem' } } }, 'description' => 'UseResponse model' }
159
159
  }
160
160
  end
161
161
 
162
162
  let(:swagger_params_as_response_object) do
163
163
  {
164
- 'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'description' => 'status code', 'type' => 'integer', 'format' => 'int32' }, 'message' => { 'description' => 'error message', 'type' => 'string' } }, 'description' => 'This returns something' }
164
+ 'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'description' => 'status code', 'type' => 'integer', 'format' => 'int32' }, 'message' => { 'description' => 'error message', 'type' => 'string' } }, 'description' => 'ApiError model' }
165
165
  }
166
166
  end
167
167
 
@@ -300,7 +300,7 @@ RSpec.shared_context 'entity swagger example' do
300
300
  'type' => 'object',
301
301
  'required' => ['elements'],
302
302
  'properties' => { 'elements' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/QueryInputElement' }, 'description' => 'Set of configuration' } },
303
- 'description' => 'nested route inside namespace'
303
+ 'description' => 'QueryInput model'
304
304
  },
305
305
  'QueryInputElement' => {
306
306
  'type' => 'object',
@@ -310,7 +310,7 @@ RSpec.shared_context 'entity swagger example' do
310
310
  'ApiError' => {
311
311
  'type' => 'object',
312
312
  'properties' => { 'code' => { 'type' => 'integer', 'format' => 'int32', 'description' => 'status code' }, 'message' => { 'type' => 'string', 'description' => 'error message' } },
313
- 'description' => 'This gets Things.'
313
+ 'description' => 'ApiError model'
314
314
  },
315
315
  'Something' => {
316
316
  'type' => 'object',
@@ -320,7 +320,7 @@ RSpec.shared_context 'entity swagger example' do
320
320
  'links' => { 'type' => 'array', 'items' => { 'type' => 'link' } },
321
321
  'others' => { 'type' => 'text' }
322
322
  },
323
- 'description' => 'This gets Things.'
323
+ 'description' => 'Something model'
324
324
  }
325
325
  }
326
326
  }
@@ -112,7 +112,7 @@ RSpec.shared_context 'mock swagger example' do
112
112
  'description' => "it's a mock"
113
113
  }
114
114
  },
115
- 'description' => 'This returns something'
115
+ 'description' => 'ApiError model'
116
116
  },
117
117
  'UseItemResponseAsType' => {
118
118
  'type' => 'object',
@@ -122,7 +122,7 @@ RSpec.shared_context 'mock swagger example' do
122
122
  'description' => "it's a mock"
123
123
  }
124
124
  },
125
- 'description' => 'This returns something'
125
+ 'description' => 'UseItemResponseAsType model'
126
126
  }
127
127
  }
128
128
  end
@@ -137,7 +137,7 @@ RSpec.shared_context 'mock swagger example' do
137
137
  'description' => "it's a mock"
138
138
  }
139
139
  },
140
- 'description' => 'This returns something'
140
+ 'description' => 'UseResponse model'
141
141
  },
142
142
  'ApiError' => {
143
143
  'type' => 'object',
@@ -147,7 +147,7 @@ RSpec.shared_context 'mock swagger example' do
147
147
  'description' => "it's a mock"
148
148
  }
149
149
  },
150
- 'description' => 'This returns something'
150
+ 'description' => 'ApiError model'
151
151
  }
152
152
  }
153
153
  end
@@ -162,7 +162,7 @@ RSpec.shared_context 'mock swagger example' do
162
162
  'description' => "it's a mock"
163
163
  }
164
164
  },
165
- 'description' => 'This returns something'
165
+ 'description' => 'ApiError model'
166
166
  }
167
167
  }
168
168
  end
@@ -296,7 +296,7 @@ RSpec.shared_context 'mock swagger example' do
296
296
  'description' => "it's a mock"
297
297
  }
298
298
  },
299
- 'description' => 'nested route inside namespace'
299
+ 'description' => 'QueryInput model'
300
300
  },
301
301
  'ApiError' => {
302
302
  'type' => 'object',
@@ -306,7 +306,7 @@ RSpec.shared_context 'mock swagger example' do
306
306
  'description' => "it's a mock"
307
307
  }
308
308
  },
309
- 'description' => 'This gets Things.'
309
+ 'description' => 'ApiError model'
310
310
  },
311
311
  'Something' => {
312
312
  'type' => 'object',
@@ -316,7 +316,7 @@ RSpec.shared_context 'mock swagger example' do
316
316
  'description' => "it's a mock"
317
317
  }
318
318
  },
319
- 'description' => 'This gets Things.'
319
+ 'description' => 'Something model'
320
320
  }
321
321
  }
322
322
  }
@@ -218,22 +218,22 @@ RSpec.shared_context 'representable swagger example' do
218
218
 
219
219
  let(:swagger_nested_type) do
220
220
  {
221
- 'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'description' => 'status code', 'type' => 'integer', 'format' => 'int32' }, 'message' => { 'description' => 'error message', 'type' => 'string' } }, 'description' => 'This returns something' },
222
- 'UseItemResponseAsType' => { 'type' => 'object', 'properties' => { 'description' => { 'description' => '', 'type' => 'string' }, 'responses' => { 'description' => '', 'type' => 'ResponseItem' } }, 'description' => 'This returns something' }
221
+ 'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'description' => 'status code', 'type' => 'integer', 'format' => 'int32' }, 'message' => { 'description' => 'error message', 'type' => 'string' } }, 'description' => 'ApiError model' },
222
+ 'UseItemResponseAsType' => { 'type' => 'object', 'properties' => { 'description' => { 'description' => '', 'type' => 'string' }, 'responses' => { 'description' => '', 'type' => 'ResponseItem' } }, 'description' => 'UseItemResponseAsType model' }
223
223
  }
224
224
  end
225
225
 
226
226
  let(:swagger_entity_as_response_object) do
227
227
  {
228
- 'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'description' => 'status code', 'type' => 'integer', 'format' => 'int32' }, 'message' => { 'description' => 'error message', 'type' => 'string' } }, 'description' => 'This returns something' },
228
+ 'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'description' => 'status code', 'type' => 'integer', 'format' => 'int32' }, 'message' => { 'description' => 'error message', 'type' => 'string' } }, 'description' => 'ApiError model' },
229
229
  'ResponseItem' => { 'type' => 'object', 'properties' => { 'id' => { 'description' => '', 'type' => 'integer', 'format' => 'int32' }, 'name' => { 'description' => '', 'type' => 'string' } } },
230
- 'UseResponse' => { 'type' => 'object', 'properties' => { 'description' => { 'description' => '', 'type' => 'string' }, '$responses' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/ResponseItem' }, 'description' => '' } }, 'description' => 'This returns something' }
230
+ 'UseResponse' => { 'type' => 'object', 'properties' => { 'description' => { 'description' => '', 'type' => 'string' }, '$responses' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/ResponseItem' }, 'description' => '' } }, 'description' => 'UseResponse model' }
231
231
  }
232
232
  end
233
233
 
234
234
  let(:swagger_params_as_response_object) do
235
235
  {
236
- 'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'description' => 'status code', 'type' => 'integer', 'format' => 'int32' }, 'message' => { 'description' => 'error message', 'type' => 'string' } }, 'description' => 'This returns something' }
236
+ 'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'description' => 'status code', 'type' => 'integer', 'format' => 'int32' }, 'message' => { 'description' => 'error message', 'type' => 'string' } }, 'description' => 'ApiError model' }
237
237
  }
238
238
  end
239
239
 
@@ -372,7 +372,7 @@ RSpec.shared_context 'representable swagger example' do
372
372
  'type' => 'object',
373
373
  'required' => ['elements'],
374
374
  'properties' => { 'elements' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/QueryInputElement' }, 'description' => 'Set of configuration' } },
375
- 'description' => 'nested route inside namespace'
375
+ 'description' => 'QueryInput model'
376
376
  },
377
377
  'QueryInputElement' => {
378
378
  'type' => 'object',
@@ -382,7 +382,7 @@ RSpec.shared_context 'representable swagger example' do
382
382
  'ApiError' => {
383
383
  'type' => 'object',
384
384
  'properties' => { 'code' => { 'type' => 'integer', 'format' => 'int32', 'description' => 'status code' }, 'message' => { 'type' => 'string', 'description' => 'error message' } },
385
- 'description' => 'This gets Things.'
385
+ 'description' => 'ApiError model'
386
386
  },
387
387
  'Something' => {
388
388
  'type' => 'object',
@@ -392,7 +392,7 @@ RSpec.shared_context 'representable swagger example' do
392
392
  'links' => { 'type' => 'array', 'items' => { 'description' => '', 'type' => 'link' } },
393
393
  'others' => { 'description' => '', 'type' => 'text' }
394
394
  },
395
- 'description' => 'This gets Things.'
395
+ 'description' => 'Something model'
396
396
  }
397
397
  }
398
398
  }
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'response' do
6
+ include_context "#{MODEL_PARSER} swagger example"
7
+
8
+ before :all do
9
+ module TheApi
10
+ class ResponseApiModels < Grape::API
11
+ format :json
12
+
13
+ desc 'This returns something',
14
+ success: [{ code: 200 }],
15
+ failure: [
16
+ { code: 400, message: 'NotFound', model: '' },
17
+ { code: 404, message: 'BadRequest', model: Entities::ApiError }
18
+ ]
19
+ get '/use-response' do
20
+ { 'declared_params' => declared(params) }
21
+ end
22
+
23
+ add_swagger_documentation(models: [Entities::UseResponse])
24
+ end
25
+ end
26
+ end
27
+
28
+ def app
29
+ TheApi::ResponseApiModels
30
+ end
31
+
32
+ describe 'uses entity as response object implicitly with route name' do
33
+ subject do
34
+ get '/swagger_doc/use-response'
35
+ JSON.parse(last_response.body)
36
+ end
37
+
38
+ specify do
39
+ expect(subject['paths']['/use-response']['get']).to eql(
40
+ 'description' => 'This returns something',
41
+ 'produces' => ['application/json'],
42
+ 'responses' => {
43
+ '200' => { 'description' => 'This returns something', 'schema' => { '$ref' => '#/definitions/UseResponse' } },
44
+ '400' => { 'description' => 'NotFound' },
45
+ '404' => { 'description' => 'BadRequest', 'schema' => { '$ref' => '#/definitions/ApiError' } }
46
+ },
47
+ 'tags' => ['use-response'],
48
+ 'operationId' => 'getUseResponse'
49
+ )
50
+ expect(subject['definitions']).to eql(swagger_entity_as_response_object)
51
+ end
52
+ end
53
+ end
@@ -103,7 +103,7 @@ describe 'referenceEntity' do
103
103
  'description' => 'Something interesting.'
104
104
  }
105
105
  },
106
- 'description' => 'This returns kind and something or an error'
106
+ 'description' => 'KindCustom model'
107
107
  )
108
108
  end
109
109
  end
@@ -122,7 +122,7 @@ describe 'referenceEntity' do
122
122
  'title' => { 'type' => 'string', 'description' => 'Title of the parent.' },
123
123
  'child' => { 'type' => 'string', 'description' => 'Child property.' }
124
124
  },
125
- 'description' => 'This returns a child entity'
125
+ 'description' => 'MyAPI::Child model'
126
126
  )
127
127
  end
128
128
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape-swagger
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Vandecasteele
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-15 00:00:00.000000000 Z
11
+ date: 2020-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: grape
@@ -140,6 +140,7 @@ files:
140
140
  - spec/swagger_v2/api_swagger_v2_response_spec.rb
141
141
  - spec/swagger_v2/api_swagger_v2_response_with_examples_spec.rb
142
142
  - spec/swagger_v2/api_swagger_v2_response_with_headers_spec.rb
143
+ - spec/swagger_v2/api_swagger_v2_response_with_models_spec.rb
143
144
  - spec/swagger_v2/api_swagger_v2_response_with_root_spec.rb
144
145
  - spec/swagger_v2/api_swagger_v2_spec.rb
145
146
  - spec/swagger_v2/api_swagger_v2_status_codes_spec.rb
@@ -264,6 +265,7 @@ test_files:
264
265
  - spec/swagger_v2/api_swagger_v2_response_spec.rb
265
266
  - spec/swagger_v2/api_swagger_v2_response_with_examples_spec.rb
266
267
  - spec/swagger_v2/api_swagger_v2_response_with_headers_spec.rb
268
+ - spec/swagger_v2/api_swagger_v2_response_with_models_spec.rb
267
269
  - spec/swagger_v2/api_swagger_v2_response_with_root_spec.rb
268
270
  - spec/swagger_v2/api_swagger_v2_spec.rb
269
271
  - spec/swagger_v2/api_swagger_v2_status_codes_spec.rb