Skip to content

Commit 60e7f2c

Browse files
committed
Merge pull request ruby-grape#420 from Bugagazavr/avoid-empty-hashes
Avoid empty hashes
2 parents 6195fa6 + 786ae36 commit 60e7f2c

File tree

9 files changed

+221
-25
lines changed

9 files changed

+221
-25
lines changed

.rubocop_todo.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This configuration was generated by
22
# `rubocop --auto-gen-config`
3-
# on 2016-05-10 15:59:21 -0400 using RuboCop version 0.40.0.
3+
# on 2016-05-11 23:53:37 +0300 using RuboCop version 0.40.0.
44
# The point is for the user to remove these configuration records
55
# one by one as the offenses are removed from the code base.
66
# Note that changes in the inspected code, or installation of new
@@ -21,26 +21,26 @@ Lint/UselessAssignment:
2121
Exclude:
2222
- 'spec/lib/move_params_spec.rb'
2323

24-
# Offense count: 26
24+
# Offense count: 27
2525
Metrics/AbcSize:
2626
Max: 56
2727

2828
# Offense count: 3
2929
# Configuration parameters: CountComments.
3030
Metrics/ClassLength:
31-
Max: 195
31+
Max: 201
3232

3333
# Offense count: 10
3434
Metrics/CyclomaticComplexity:
3535
Max: 16
3636

37-
# Offense count: 711
37+
# Offense count: 719
3838
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes.
3939
# URISchemes: http, https
4040
Metrics/LineLength:
4141
Max: 454
4242

43-
# Offense count: 30
43+
# Offense count: 31
4444
# Configuration parameters: CountComments.
4545
Metrics/MethodLength:
4646
Max: 101

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
#### Fixes
99

1010
* [#416](https://github.com/ruby-grape/grape-swagger/pull/416): Support recursive models - [@lest](https://github.com/lest).
11-
* [#418](https://github.com/ruby-grape/grape-swagger/pull/418): Replaced github ref to rubygems for external gems - [@Bugagazavr](https://github.com/Bugagazavr).
11+
* [#419](https://github.com/ruby-grape/grape-swagger/pull/419): Replaced github ref to rubygems for external gems - [@Bugagazavr](https://github.com/Bugagazavr).
12+
* [#420](https://github.com/ruby-grape/grape-swagger/pull/420): Raise SwaggerSpec exception if swagger spec isn't satisfied, when no parser for model registred or response model is empty - [@Bugagazavr](https://github.com/Bugagazavr).
1213

1314
### 0.20.3 (May 9, 2016)
1415

lib/grape-swagger/endpoint.rb

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -232,17 +232,23 @@ def expose_params_from_model(model)
232232
return model_name if @definitions.key?(model_name)
233233
@definitions[model_name] = nil
234234

235-
properties = {}
235+
properties = nil
236+
parser = nil
237+
236238
GrapeSwagger.model_parsers.each do |klass, ancestor|
237239
next unless model.ancestors.map(&:to_s).include?(ancestor)
238240

239-
model_class = klass.new(model, self)
240-
properties = model_class.call
241+
parser = klass.new(model, self)
241242

242243
break
243244
end
244245

245-
@definitions[model_name] = { type: 'object', properties: properties || {} }
246+
properties = parser.call unless parser.nil?
247+
248+
raise GrapeSwagger::Errors::UnregisteredParser, "No parser registred for #{model_name}." unless parser
249+
raise GrapeSwagger::Errors::SwaggerSpec, "Empty model #{model_name}, swagger 2.0 doesn't support empty definitions." unless properties && properties.any?
250+
251+
@definitions[model_name] = { type: 'object', properties: properties }
246252

247253
model_name
248254
end

lib/grape-swagger/errors.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,8 @@ def initialize(missing_gem)
55
super("Missing required dependency: #{missing_gem}")
66
end
77
end
8+
9+
class UnregisteredParser < StandardError; end
10+
class SwaggerSpec < StandardError; end
811
end
912
end

spec/spec_helper.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
22

3-
Dir[File.join(Dir.getwd, 'spec/support/*.rb')].each { |f| require f }
43
MODEL_PARSER = ENV.key?('MODEL_PARSER') ? ENV['MODEL_PARSER'].to_s.downcase.sub('grape-swagger-', '') : 'mock'
54

65
require 'grape'
76
require 'grape-swagger'
7+
Dir[File.join(Dir.getwd, 'spec/support/*.rb')].each { |f| require f }
88
require "grape-swagger/#{MODEL_PARSER}" if MODEL_PARSER != 'mock'
99
require File.join(Dir.getwd, "spec/support/model_parsers/#{MODEL_PARSER}_parser.rb")
1010

spec/support/empty_model_parser.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
class EmptyClass
2+
end
3+
4+
module GrapeSwagger
5+
class EmptyModelParser
6+
attr_reader :model
7+
attr_reader :endpoint
8+
9+
def initialize(model, endpoint)
10+
@model = model
11+
@endpoint = endpoint
12+
end
13+
14+
def call
15+
{}
16+
end
17+
end
18+
end
19+
20+
GrapeSwagger.model_parsers.register(GrapeSwagger::EmptyModelParser, EmptyClass)

spec/support/mock_parser.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
module GrapeSwagger
2+
class MockParser
3+
attr_reader :model
4+
attr_reader :endpoint
5+
6+
def initialize(model, endpoint)
7+
@model = model
8+
@endpoint = endpoint
9+
end
10+
11+
def call
12+
{
13+
mock_data: {
14+
type: :string,
15+
description: "it's a mock"
16+
}
17+
}
18+
end
19+
end
20+
end
21+
22+
GrapeSwagger.model_parsers.register(GrapeSwagger::MockParser, OpenStruct)

spec/support/model_parsers/mock_parser.rb

Lines changed: 83 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -57,22 +57,56 @@ class RecursiveModel < OpenStruct; end
5757

5858
let(:swagger_definitions_models) do
5959
{
60-
'ApiError' => { 'type' => 'object', 'properties' => {} },
61-
'UseResponse' => { 'type' => 'object', 'properties' => {} },
62-
'RecursiveModel' => { 'type' => 'object', 'properties' => {} }
60+
'ApiError' => {
61+
'type' => 'object',
62+
'properties' => {
63+
'mock_data' => {
64+
'type' => 'string',
65+
'description' => "it's a mock"
66+
}
67+
}
68+
},
69+
'RecursiveModel' => {
70+
'type' => 'object',
71+
'properties' => {
72+
'mock_data' => {
73+
'type' => 'string',
74+
'description' => "it's a mock"
75+
}
76+
}
77+
},
78+
'UseResponse' => {
79+
'type' => 'object',
80+
'properties' => {
81+
'mock_data' => {
82+
'type' => 'string',
83+
'description' => "it's a mock"
84+
}
85+
}
86+
}
6387
}
6488
end
6589

6690
let(:swagger_nested_type) do
6791
{
68-
'UseItemResponseAsType' => {
92+
'ApiError' => {
6993
'type' => 'object',
70-
'properties' => {},
94+
'properties' => {
95+
'mock_data' => {
96+
'type' => 'string',
97+
'description' => "it's a mock"
98+
}
99+
},
71100
'description' => 'This returns something'
72101
},
73-
'ApiError' => {
102+
'UseItemResponseAsType' => {
74103
'type' => 'object',
75-
'properties' => {},
104+
'properties' => {
105+
'mock_data' => {
106+
'type' => 'string',
107+
'description' => "it's a mock"
108+
}
109+
},
76110
'description' => 'This returns something'
77111
}
78112
}
@@ -82,12 +116,22 @@ class RecursiveModel < OpenStruct; end
82116
{
83117
'UseResponse' => {
84118
'type' => 'object',
85-
'properties' => {},
119+
'properties' => {
120+
'mock_data' => {
121+
'type' => 'string',
122+
'description' => "it's a mock"
123+
}
124+
},
86125
'description' => 'This returns something'
87126
},
88127
'ApiError' => {
89128
'type' => 'object',
90-
'properties' => {},
129+
'properties' => {
130+
'mock_data' => {
131+
'type' => 'string',
132+
'description' => "it's a mock"
133+
}
134+
},
91135
'description' => 'This returns something'
92136
}
93137
}
@@ -97,14 +141,24 @@ class RecursiveModel < OpenStruct; end
97141
{
98142
'ApiError' => {
99143
'type' => 'object',
100-
'properties' => {},
144+
'properties' => {
145+
'mock_data' => {
146+
'type' => 'string',
147+
'description' => "it's a mock"
148+
}
149+
},
101150
'description' => 'This returns something'
102151
}
103152
}
104153
end
105154

106155
let(:swagger_typed_defintion) do
107-
{}
156+
{
157+
'mock_data' => {
158+
'type' => 'string',
159+
'description' => "it's a mock"
160+
}
161+
}
108162
end
109163

110164
let(:swagger_json) do
@@ -221,17 +275,32 @@ class RecursiveModel < OpenStruct; end
221275
'definitions' => {
222276
'QueryInput' => {
223277
'type' => 'object',
224-
'properties' => {},
278+
'properties' => {
279+
'mock_data' => {
280+
'type' => 'string',
281+
'description' => "it's a mock"
282+
}
283+
},
225284
'description' => 'nested route inside namespace'
226285
},
227286
'ApiError' => {
228287
'type' => 'object',
229-
'properties' => {},
288+
'properties' => {
289+
'mock_data' => {
290+
'type' => 'string',
291+
'description' => "it's a mock"
292+
}
293+
},
230294
'description' => 'This gets Things.'
231295
},
232296
'Something' => {
233297
'type' => 'object',
234-
'properties' => {},
298+
'properties' => {
299+
'mock_data' => {
300+
'type' => 'string',
301+
'description' => "it's a mock"
302+
}
303+
},
235304
'description' => 'This gets Things.'
236305
}
237306
}

spec/swagger_v2/errors_spec.rb

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
require 'spec_helper'
2+
3+
describe 'Errors' do
4+
describe 'Empty model error' do
5+
let!(:app) do
6+
Class.new(Grape::API) do
7+
format :json
8+
9+
desc 'Empty model get.' do
10+
http_codes [
11+
{ code: 200, message: 'get Empty model', model: EmptyClass }
12+
]
13+
end
14+
get '/empty_model' do
15+
something = OpenStruct.new text: 'something'
16+
present something, with: EmptyClass
17+
end
18+
19+
version 'v3', using: :path
20+
add_swagger_documentation api_version: 'v1',
21+
base_path: '/api',
22+
info: {
23+
title: 'The API title to be displayed on the API homepage.',
24+
description: 'A description of the API.',
25+
contact_name: 'Contact name',
26+
contact_email: '[email protected]',
27+
contact_url: 'Contact URL',
28+
license: 'The name of the license.',
29+
license_url: 'www.The-URL-of-the-license.org',
30+
terms_of_service_url: 'www.The-URL-of-the-terms-and-service.com'
31+
}
32+
end
33+
end
34+
35+
it 'should raise SwaggerSpec exception' do
36+
expect { get '/v3/swagger_doc' }.to raise_error(GrapeSwagger::Errors::SwaggerSpec, "Empty model EmptyClass, swagger 2.0 doesn't support empty definitions.")
37+
end
38+
end
39+
40+
describe 'Parser not found error' do
41+
let!(:app) do
42+
Class.new(Grape::API) do
43+
format :json
44+
45+
desc 'Wrong model get.' do
46+
http_codes [
47+
{ code: 200, message: 'get Wrong model', model: Hash }
48+
]
49+
end
50+
get '/wrong_model' do
51+
something = OpenStruct.new text: 'something'
52+
present something, with: Hash
53+
end
54+
55+
version 'v3', using: :path
56+
add_swagger_documentation api_version: 'v1',
57+
base_path: '/api',
58+
info: {
59+
title: 'The API title to be displayed on the API homepage.',
60+
description: 'A description of the API.',
61+
contact_name: 'Contact name',
62+
contact_email: '[email protected]',
63+
contact_url: 'Contact URL',
64+
license: 'The name of the license.',
65+
license_url: 'www.The-URL-of-the-license.org',
66+
terms_of_service_url: 'www.The-URL-of-the-terms-and-service.com'
67+
}
68+
end
69+
end
70+
71+
it 'should raise UnregisteredParser exception' do
72+
expect { get '/v3/swagger_doc' }.to raise_error(GrapeSwagger::Errors::UnregisteredParser, 'No parser registred for Hash.')
73+
end
74+
end
75+
end

0 commit comments

Comments
 (0)