Skip to content

Commit 168146d

Browse files
author
Peter Scholz
committed
adds format to definition property type
1 parent 8d6d04a commit 168146d

10 files changed

+284
-141
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ env:
1616
- GRAPE_VERSION=0.12.0
1717
- GRAPE_VERSION=0.13.0
1818
- GRAPE_VERSION=0.14.0
19-
- GRAPE_VERSION=HEAD
19+
# - GRAPE_VERSION=HEAD

lib/grape-swagger/doc_methods/data_type.rb

+27-8
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,20 @@ def call(value)
66
raw_data_type = value[:type] if value.is_a?(Hash)
77
raw_data_type ||= 'string'
88
case raw_data_type.to_s
9+
when 'Boolean', 'Date', 'Integer', 'String', 'Float', 'JSON', 'Array'
10+
raw_data_type.to_s.downcase
911
when 'Hash'
1012
'object'
11-
when 'Rack::Multipart::UploadedFile'
12-
'File'
13+
when 'Rack::Multipart::UploadedFile', 'File'
14+
'file'
1315
when 'Virtus::Attribute::Boolean'
1416
'boolean'
15-
when 'Boolean', 'Date', 'Integer', 'String', 'Float'
16-
raw_data_type.to_s.downcase
1717
when 'BigDecimal'
18-
'long'
19-
when 'DateTime'
18+
'double'
19+
when 'DateTime', 'Time'
2020
'dateTime'
2121
when 'Numeric'
22-
'double'
22+
'long'
2323
when 'Symbol'
2424
'string'
2525
else
@@ -37,6 +37,22 @@ def parse_entity_name(model)
3737
entity_parts.join('::')
3838
end
3939
end
40+
41+
def request_primitive?(type)
42+
request_primitives.include?(type.to_s.downcase)
43+
end
44+
45+
def primitive?(type)
46+
primitives.include?(type.to_s.downcase)
47+
end
48+
49+
def request_primitives
50+
primitives + %w(object string boolean file json array)
51+
end
52+
53+
def primitives
54+
PRIMITIVE_MAPPINGS.keys.map(&:downcase)
55+
end
4056
end
4157

4258
PRIMITIVE_MAPPINGS = {
@@ -46,7 +62,10 @@ def parse_entity_name(model)
4662
'double' => %w(number double),
4763
'byte' => %w(string byte),
4864
'date' => %w(string date),
49-
'dateTime' => %w(string date-time)
65+
'dateTime' => %w(string date-time),
66+
'binary' => %w(string binary),
67+
'password' => %w(string password),
68+
'email' => %w(string email)
5069
}.freeze
5170
end
5271
end

lib/grape-swagger/doc_methods/parse_params.rb

+18-21
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,19 @@ def call(param, value, route)
77
path = route.route_path
88
method = route.route_method
99

10-
additional_documentation = value.is_a?(Hash) ? value[:documentation] : nil
1110
data_type = GrapeSwagger::DocMethods::DataType.call(value)
12-
13-
if additional_documentation && value.is_a?(Hash)
11+
additional_documentation = value[:documentation]
12+
if additional_documentation
1413
value = additional_documentation.merge(value)
1514
end
1615

17-
description = value.is_a?(Hash) ? value[:desc] || value[:description] : nil
18-
required = value.is_a?(Hash) ? value[:required] : false
19-
default_value = value.is_a?(Hash) ? value[:default] : nil
20-
example = value.is_a?(Hash) ? value[:example] : nil
21-
is_array = value.is_a?(Hash) ? (value[:is_array] || false) : false
22-
values = value.is_a?(Hash) ? value[:values] : nil
23-
name = (value.is_a?(Hash) && value[:full_name]) || param
16+
description = value[:desc] || value[:description] || nil
17+
required = value[:required] || false
18+
default_value = value[:default] || nil
19+
example = value[:example] || nil
20+
is_array = value[:is_array] || false
21+
values = value[:values] || nil
22+
name = value[:full_name] || param
2423
enum_or_range_values = parse_enum_or_range_values(values)
2524

2625
value_type = { value: value, data_type: data_type, path: path }
@@ -29,31 +28,29 @@ def call(param, value, route)
2928
in: param_type(value_type, param, method, is_array),
3029
name: name,
3130
description: description,
32-
type: data_type,
3331
required: required
3432
}
3533

36-
if GrapeSwagger::DocMethods::DataType::PRIMITIVE_MAPPINGS.key?(data_type)
37-
parsed_params[:type], parsed_params[:format] = GrapeSwagger::DocMethods::DataType::PRIMITIVE_MAPPINGS[data_type]
34+
if GrapeSwagger::DocMethods::DataType.primitive?(data_type)
35+
data = GrapeSwagger::DocMethods::DataType::PRIMITIVE_MAPPINGS[data_type]
36+
parsed_params[:type], parsed_params[:format] = data
37+
else
38+
parsed_params[:type] = data_type
3839
end
3940

4041
parsed_params[:items] = @array_items if @array_items.present?
4142

42-
parsed_params[:defaultValue] = example if example
43-
parsed_params[:defaultValue] = default_value if default_value && example.blank?
43+
parsed_params[:default] = example if example
44+
parsed_params[:default] = default_value if default_value && example.blank?
4445

4546
parsed_params.merge!(enum_or_range_values) if enum_or_range_values
4647
parsed_params
4748
end
4849

49-
def primitive?(type)
50-
%w(object integer long float double string byte boolean date datetime).include? type.to_s.downcase
51-
end
52-
5350
private
5451

5552
def param_type(value_type, param, method, is_array)
56-
# TODO: use `value_type.dig():value, :documentation, :param_type)` instead req ruby2.3
53+
# TODO: use `value_type.dig():value, :documentation, :param_type)` instead, req ruby2.3
5754
#
5855
if value_type[:value].is_a?(Hash) &&
5956
value_type[:value].key?(:documentation) &&
@@ -69,7 +66,7 @@ def param_type(value_type, param, method, is_array)
6966
when value_type[:path].include?("{#{param}}")
7067
'path'
7168
when %w(POST PUT PATCH).include?(method)
72-
primitive?(value_type[:data_type]) ? 'formData' : 'body'
69+
GrapeSwagger::DocMethods::DataType.request_primitive?(value_type[:data_type]) ? 'formData' : 'body'
7370
else
7471
'query'
7572
end

lib/grape-swagger/endpoint.rb

+11-2
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,16 @@ def parse_response_params(params)
238238
{ '$ref' => "#/definitions/#{name}" }
239239
end
240240
else
241-
memo[x.first] = { type: GrapeSwagger::DocMethods::DataType.call(x.last[:documentation] || x.last) }
241+
242+
data_type = GrapeSwagger::DocMethods::DataType.call(x.last[:documentation] || x.last)
243+
244+
if GrapeSwagger::DocMethods::DataType.primitive?(data_type)
245+
data = GrapeSwagger::DocMethods::DataType::PRIMITIVE_MAPPINGS[data_type]
246+
memo[x.first] = { type: data.first, format: data.last }
247+
else
248+
memo[x.first] = { type: data_type }
249+
end
250+
242251
memo[x.first][:enum] = x.last[:values] if x.last[:values] && x.last[:values].is_a?(Array)
243252
end
244253
end
@@ -269,7 +278,7 @@ def could_it_be_a_model?(value)
269278
) || (
270279
value[:type] &&
271280
value[:type].is_a?(Class) &&
272-
!GrapeSwagger::DocMethods::ParseParams.primitive?(value[:type].name.downcase) &&
281+
!GrapeSwagger::DocMethods::DataType.primitive?(value[:type].name.downcase) &&
273282
!value[:type] == Array
274283
)
275284
end

spec/lib/data_type_spec.rb

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
describe "Rack::Multipart::UploadedFile" do
2323
let(:value) { { type: Rack::Multipart::UploadedFile } }
2424

25-
it { expect(subject).to eql 'File' }
25+
it { expect(subject).to eql 'file' }
2626
end
2727

2828
describe "Virtus::Attribute::Boolean" do
@@ -34,7 +34,7 @@
3434
describe "BigDecimal" do
3535
let(:value) { { type: BigDecimal } }
3636

37-
it { expect(subject).to eql 'long' }
37+
it { expect(subject).to eql 'double' }
3838
end
3939

4040
describe "DateTime" do
@@ -46,7 +46,7 @@
4646
describe "Numeric" do
4747
let(:value) { { type: Numeric } }
4848

49-
it { expect(subject).to eql 'double' }
49+
it { expect(subject).to eql 'long' }
5050
end
5151

5252
describe "Symbol" do

spec/support/api_swagger_v2_result.rb

+93-95
Original file line numberDiff line numberDiff line change
@@ -67,104 +67,102 @@ class ApiError < Grape::Entity
6767
"termsOfServiceUrl"=>"www.The-URL-of-the-terms-and-service.com",
6868
"contact"=>{"name"=>"Contact name", "email"=>"[email protected]", "url"=>"Contact URL"},
6969
"license"=>{"name"=>"The name of the license.", "url"=>"www.The-URL-of-the-license.org"},
70-
"version"=>"v1"
71-
},
72-
"swagger"=>"2.0",
73-
"produces"=>["application/json"],
74-
"host"=>"example.org",
75-
"basePath"=>"/api",
76-
"tags"=>[{"name"=>"other_thing", "description"=>"Operations about other_things"},
77-
{"name"=>"thing", "description"=>"Operations about things"},
78-
{"name"=>"thing2", "description"=>"Operations about thing2s"},
79-
{"name"=>"dummy", "description"=>"Operations about dummies"}],
80-
"schemes"=>["https", "http"],
81-
"paths"=>{
82-
"/v3/other_thing/{elements}"=>{
83-
"get"=>{
84-
"produces"=>["application/json"],
85-
"parameters"=>[
86-
{"in"=>"array", "name"=>"elements", "description"=>"Set of configuration", "type"=>"string", "required"=>true, "items"=>{"type"=>"string"}}],
70+
"version"=>"v1"},
71+
"swagger"=>"2.0",
72+
"produces"=>["application/json"],
73+
"host"=>"example.org",
74+
"basePath"=>"/api",
75+
"tags"=>[
76+
{"name"=>"other_thing", "description"=>"Operations about other_things"},
77+
{"name"=>"thing", "description"=>"Operations about things"},
78+
{"name"=>"thing2", "description"=>"Operations about thing2s"},
79+
{"name"=>"dummy", "description"=>"Operations about dummies"}
80+
],
81+
"schemes"=>["https", "http"],
82+
"paths"=>{
83+
"/v3/other_thing/{elements}"=>{
84+
"get"=>{
85+
"produces"=>["application/json"],
86+
"parameters"=>[{"in"=>"array", "name"=>"elements", "description"=>"Set of configuration", "required"=>true, "type"=>"string", "items"=>{"type"=>"string"}}],
87+
"responses"=>{"200"=>{"description"=>"nested route inside namespace", "schema"=>{"$ref"=>"#/definitions/QueryInput"}}},
8788
"tags"=>["other_thing"],
8889
"operationId"=>"getV3OtherThingElements",
89-
"responses"=>{"200"=>{"description"=>"nested route inside namespace", "schema"=>{"$ref"=>"#/definitions/QueryInput"}}},
9090
"x-amazon-apigateway-auth"=>{"type"=>"none"},
91-
"x-amazon-apigateway-integration"=>{"type"=>"aws", "uri"=>"foo_bar_uri", "httpMethod"=>"get"}}},
92-
"/thing"=>{
93-
"get"=>{
94-
"produces"=>["application/json"],
95-
"parameters"=>[
96-
{"in"=>"query", "name"=>"id", "description"=>"Identity of Something", "type"=>"integer", "required"=>false, "format"=>"int32"},
97-
{"in"=>"query", "name"=>"text", "description"=>"Content of something.", "type"=>"string", "required"=>false},
98-
{"in"=>"query", "name"=>"links", "description"=>nil, "type"=>"link", "required"=>false},
99-
{"in"=>"query", "name"=>"others", "description"=>nil, "type"=>"text", "required"=>false}],
100-
"tags"=>["thing"],
101-
"operationId"=>"getThing",
102-
"responses"=>{
103-
"200"=>{"description"=>"This gets Things.", "schema"=>{"$ref"=>"#/definitions/Thing"}},
104-
"401"=>{"description"=>"Unauthorized", "schema"=>{"$ref"=>"#/definitions/ApiError"}}}},
105-
"post"=>{
106-
"produces"=>["application/json"],
107-
"consumes"=>["application/json"],
108-
"parameters"=>[
109-
{"in"=>"formData", "name"=>"text", "description"=>"Content of something.", "type"=>"string", "required"=>true},
110-
{"in"=>"body", "name"=>"links", "description"=>nil, "type"=>"Array", "required"=>true}],
111-
"tags"=>["thing"],
112-
"operationId"=>"postThing",
113-
"responses"=>{
114-
"201"=>{"description"=>"This creates Thing.", "schema"=>{"$ref"=>"#/definitions/Something"}},
115-
"422"=>{"description"=>"Unprocessible Entity"}}
116-
}},
117-
"/thing/{id}"=>{
118-
"get"=>{
119-
"produces"=>["application/json"],
120-
"parameters"=>[
121-
{"in"=>"path", "name"=>"id", "description"=>nil, "type"=>"integer", "required"=>true, "format"=>"int32"}],
122-
"tags"=>["thing"],
123-
"operationId"=>"getThingId",
124-
"responses"=>{
125-
"200"=>{"description"=>"getting a single thing", "schema"=>{"$ref"=>"#/definitions/Thing"}},
126-
"401"=>{"description"=>"Unauthorized"}}},
127-
"put"=>{
128-
"produces"=>["application/json"],
129-
"consumes"=>["application/json"],
130-
"parameters"=>[
131-
{"in"=>"path", "name"=>"id", "description"=>nil, "type"=>"integer", "required"=>true, "format"=>"int32"},
132-
{"in"=>"formData", "name"=>"text", "description"=>"Content of something.", "type"=>"string", "required"=>false},
133-
{"in"=>"body", "name"=>"links", "description"=>nil, "type"=>"Array", "required"=>false}],
134-
"tags"=>["thing"],
135-
"operationId"=>"putThingId",
136-
"responses"=>{"200"=>{"description"=>"This updates Thing.", "schema"=>{"$ref"=>"#/definitions/Something"}}}},
137-
"delete"=>{
138-
"produces"=>["application/json"],
139-
"parameters"=>[{"in"=>"path", "name"=>"id", "description"=>nil, "type"=>"integer", "required"=>true, "format"=>"int32"}],
140-
"tags"=>["thing"],
141-
"operationId"=>"deleteThingId",
142-
"responses"=>{"200"=>{"description"=>"This deletes Thing.", "schema"=>{"$ref"=>"#/definitions/Something"}}}
143-
}},
144-
"/thing2"=>{
145-
"get"=>{
146-
"produces"=>["application/json"],
147-
"tags"=>["thing2"],
148-
"operationId"=>"getThing2",
149-
"responses"=>{
150-
"200"=>{"description"=>"get Horses", "schema"=>{"$ref"=>"#/definitions/Something"}},
151-
"401"=>{"description"=>"HorsesOutError", "schema"=>{"$ref"=>"#/definitions/ApiError"}}}
152-
}},
153-
"/dummy/{id}"=>{
154-
"delete"=>{
155-
"produces"=>["application/json"],
156-
"parameters"=>[{"in"=>"path", "name"=>"id", "description"=>nil, "type"=>"integer", "required"=>true, "format"=>"int32"}],
157-
"tags"=>["dummy"],
158-
"operationId"=>"deleteDummyId",
159-
"responses"=>{"200"=>{"description"=>"dummy route."}, "401"=>{"description"=>"Unauthorized"}}
160-
}}},
161-
"definitions"=>{
162-
"QueryInputElement"=>{"type"=>"object", "properties"=>{"key"=>{"type"=>"string"}, "value"=>{"type"=>"string"}}},
163-
"QueryInput"=>{"type"=>"object", "properties"=>{"elements"=>{"type"=>"array", "items"=>{"$ref"=>"#/definitions/QueryInputElement"}}}},
164-
"Thing"=>{"properties"=>{"id"=>{"type"=>"integer"}, "text"=>{"type"=>"string"}, "links"=>{"type"=>"link"}, "others"=>{"type"=>"text"}}},
165-
"ApiError"=>{"type"=>"object", "properties"=>{"code"=>{"type"=>"integer"}, "message"=>{"type"=>"string"}}},
166-
"Something"=>{"type"=>"object", "properties"=>{"id"=>{"type"=>"integer"}, "text"=>{"type"=>"string"}, "links"=>{"type"=>"link"}, "others"=>{"type"=>"text"}}}
167-
}}
91+
"x-amazon-apigateway-integration"=>{"type"=>"aws", "uri"=>"foo_bar_uri", "httpMethod"=>"get"}
92+
}},
93+
"/thing"=>{
94+
"get"=>{
95+
"produces"=>["application/json"],
96+
"parameters"=>[
97+
{"in"=>"query", "name"=>"id", "description"=>"Identity of Something", "required"=>false, "type"=>"integer", "format"=>"int32"},
98+
{"in"=>"query", "name"=>"text", "description"=>"Content of something.", "required"=>false, "type"=>"string"},
99+
{"in"=>"query", "name"=>"links", "description"=>nil, "required"=>false, "type"=>"link"},
100+
{"in"=>"query", "name"=>"others", "description"=>nil, "required"=>false, "type"=>"text"}
101+
],
102+
"responses"=>{"200"=>{"description"=>"This gets Things.", "schema"=>{"$ref"=>"#/definitions/Thing"}}, "401"=>{"description"=>"Unauthorized", "schema"=>{"$ref"=>"#/definitions/ApiError"}}},
103+
"tags"=>["thing"],
104+
"operationId"=>"getThing"
105+
},
106+
"post"=>{
107+
"produces"=>["application/json"],
108+
"consumes"=>["application/json"],
109+
"parameters"=>[
110+
{"in"=>"formData", "name"=>"text", "description"=>"Content of something.", "required"=>true, "type"=>"string"},
111+
{"in"=>"formData", "name"=>"links", "description"=>nil, "required"=>true, "type"=>"array"}
112+
],
113+
"responses"=>{"201"=>{"description"=>"This creates Thing.", "schema"=>{"$ref"=>"#/definitions/Something"}}, "422"=>{"description"=>"Unprocessible Entity"}},
114+
"tags"=>["thing"],
115+
"operationId"=>"postThing"
116+
}},
117+
"/thing/{id}"=>{
118+
"get"=>{
119+
"produces"=>["application/json"],
120+
"parameters"=>[{"in"=>"path", "name"=>"id", "description"=>nil, "required"=>true, "type"=>"integer", "format"=>"int32"}],
121+
"responses"=>{"200"=>{"description"=>"getting a single thing", "schema"=>{"$ref"=>"#/definitions/Thing"}}, "401"=>{"description"=>"Unauthorized"}},
122+
"tags"=>["thing"],
123+
"operationId"=>"getThingId"
124+
},
125+
"put"=>{
126+
"produces"=>["application/json"],
127+
"consumes"=>["application/json"],
128+
"parameters"=>[
129+
{"in"=>"path", "name"=>"id", "description"=>nil, "required"=>true, "type"=>"integer", "format"=>"int32"},
130+
{"in"=>"formData", "name"=>"text", "description"=>"Content of something.", "required"=>false, "type"=>"string"},
131+
{"in"=>"formData", "name"=>"links", "description"=>nil, "required"=>false, "type"=>"array"}
132+
],
133+
"responses"=>{"200"=>{"description"=>"This updates Thing.", "schema"=>{"$ref"=>"#/definitions/Something"}}},
134+
"tags"=>["thing"],
135+
"operationId"=>"putThingId"
136+
},
137+
"delete"=>{
138+
"produces"=>["application/json"],
139+
"parameters"=>[{"in"=>"path", "name"=>"id", "description"=>nil, "required"=>true, "type"=>"integer", "format"=>"int32"}],
140+
"responses"=>{"200"=>{"description"=>"This deletes Thing.", "schema"=>{"$ref"=>"#/definitions/Something"}}},
141+
"tags"=>["thing"],
142+
"operationId"=>"deleteThingId"
143+
}},
144+
"/thing2"=>{
145+
"get"=>{
146+
"produces"=>["application/json"],
147+
"responses"=>{"200"=>{"description"=>"get Horses", "schema"=>{"$ref"=>"#/definitions/Something"}}, "401"=>{"description"=>"HorsesOutError", "schema"=>{"$ref"=>"#/definitions/ApiError"}}},
148+
"tags"=>["thing2"],
149+
"operationId"=>"getThing2"
150+
}},
151+
"/dummy/{id}"=>{
152+
"delete"=>{
153+
"produces"=>["application/json"],
154+
"parameters"=>[{"in"=>"path", "name"=>"id", "description"=>nil, "required"=>true, "type"=>"integer", "format"=>"int32"}],
155+
"responses"=>{"200"=>{"description"=>"dummy route."}, "401"=>{"description"=>"Unauthorized"}},
156+
"tags"=>["dummy"],
157+
"operationId"=>"deleteDummyId"
158+
}}},
159+
"definitions"=>{
160+
"QueryInputElement"=>{"type"=>"object", "properties"=>{"key"=>{"type"=>"string"}, "value"=>{"type"=>"string"}}},
161+
"QueryInput"=>{"type"=>"object", "properties"=>{"elements"=>{"type"=>"array", "items"=>{"$ref"=>"#/definitions/QueryInputElement"}}}},
162+
"Thing"=>{"properties"=>{"id"=>{"type"=>"integer", "format"=>"int32"}, "text"=>{"type"=>"string"}, "links"=>{"type"=>"link"}, "others"=>{"type"=>"text"}}},
163+
"ApiError"=>{"type"=>"object", "properties"=>{"code"=>{"type"=>"integer", "format"=>"int32"}, "message"=>{"type"=>"string"}}},
164+
"Something"=>{"type"=>"object", "properties"=>{"id"=>{"type"=>"integer", "format"=>"int32"}, "text"=>{"type"=>"string"}, "links"=>{"type"=>"link"}, "others"=>{"type"=>"text"}}}
165+
}}
168166
end
169167

170168
let(:http_verbs) { %w[get post put delete]}

0 commit comments

Comments
 (0)