Skip to content

Commit

Permalink
WIP: Add support for primitive data types in responses
Browse files Browse the repository at this point in the history
  • Loading branch information
gregg-platogo committed Nov 22, 2024
1 parent ecafd1f commit 129e7d7
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 2 deletions.
19 changes: 17 additions & 2 deletions lib/grape-swagger/endpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ def params_object(route, options, path, consumes)
parameters.presence
end

def response_object(route, options)
def response_object(route, options) # rubocop:disable Metrics/PerceivedComplexity
codes(route).each_with_object({}) do |value, memo|
value[:message] ||= ''
memo[value[:code]] = { description: value[:message] ||= '' } unless memo[value[:code]].present?
Expand All @@ -212,6 +212,8 @@ def response_object(route, options)
value[:code] = 204
next
end
# Build primitive type response
build_primitive_response(memo, route, value, options) if value[:type]

# Explicitly request no model with { model: '' }
next if value[:model] == ''
Expand Down Expand Up @@ -284,6 +286,18 @@ def default_code_from_route(route)
[default_code]
end

def build_primitive_response(memo, _route, value, _options)
type = GrapeSwagger::DocMethods::DataType.call(value[:type])

if memo[value[:code]].include?(:schema) && value.include?(:as)
memo[value[:code]][:schema][:properties].merge!(value[:as] => { type: type })
elsif value.include?(:as)
memo[value[:code]][:schema] = { type: :object, properties: { value[:as] => { type: type } } }
else
memo[value[:code]][:schema] = { type: type }
end
end

def build_memo_schema(memo, route, value, response_model, options)
if memo[value[:code]][:schema] && value[:as]
memo[value[:code]][:schema][:properties].merge!(build_reference(route, value, response_model, options))
Expand Down Expand Up @@ -382,7 +396,7 @@ def merge_params(route)

# Iterates over namespaces recursively
# to build a hash of path params with options, including type
def get_path_params(stackable_values)
def get_path_params(stackable_values) # rubocop:disable Style/SafeNavigationChainLength
params = {}
return param unless stackable_values
return params unless stackable_values.is_a? Grape::Util::StackableValues
Expand Down Expand Up @@ -464,6 +478,7 @@ def success_code_from_entity(route, entity)
default_code[:as] = entity[:as] if entity[:as]
default_code[:is_array] = entity[:is_array] if entity[:is_array]
default_code[:required] = entity[:required] if entity[:required]
default_code[:type] = entity[:type] if entity[:type]
else
default_code = GrapeSwagger::DocMethods::StatusCodes.get[route.request_method.downcase.to_sym]
default_code[:model] = entity if entity
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# frozen_string_literal: true

require 'spec_helper'

describe 'response' do
include_context "#{MODEL_PARSER} swagger example"

before :all do
module TheApi
class ResponseApiModels < Grape::API
format :json

desc 'This returns something',
success: [
{ model: Entities::UseResponse, as: :user_response },
{ type: 'Integer', as: :integer_response }
],
failure: [
{ code: 400, message: 'NotFound', model: '' },
{ code: 404, message: 'BadRequest', model: Entities::ApiError }
],
default_response: { message: 'Error', model: Entities::ApiError }
get '/use-response' do
{ 'declared_params' => declared(params) }
end

add_swagger_documentation
end
end
end

def app
TheApi::ResponseApiModels
end

describe 'uses entity as response object implicitly with route name' do
subject do
get '/swagger_doc/use-response'
JSON.parse(last_response.body)
end

specify do
expect(subject['paths']['/use-response']['get']).to eql(
'description' => 'This returns something',
'produces' => ['application/json'],
'responses' => {
'200' => {
'description' => 'This returns something',
'schema' => {
'type' => 'object',
'properties' => {
'user_response' => { '$ref' => '#/definitions/UseResponse' },
'integer_response' => { 'type' => 'integer' }
}
}
},
'400' => { 'description' => 'NotFound' },
'404' => { 'description' => 'BadRequest', 'schema' => { '$ref' => '#/definitions/ApiError' } },
'default' => { 'description' => 'Error', 'schema' => { '$ref' => '#/definitions/ApiError' } }
},
'tags' => ['use-response'],
'operationId' => 'getUseResponse'
)
expect(subject['definitions']).to eql(swagger_entity_as_response_object)
end
end
end

0 comments on commit 129e7d7

Please sign in to comment.