|
| 1 | +# frozen_string_literal: true |
| 2 | + |
| 3 | +module GrapeSwagger |
| 4 | + module DocMethods |
| 5 | + class ParseRequestBody |
| 6 | + class << self |
| 7 | + def call(param, settings, path, route, _definitions) |
| 8 | + method = route.request_method |
| 9 | + additional_documentation = settings.fetch(:documentation, {}) |
| 10 | + settings.merge!(additional_documentation) |
| 11 | + data_type = DataType.call(settings) |
| 12 | + |
| 13 | + value_type = settings.merge(data_type: data_type, path: path, param_name: param, method: method) |
| 14 | + |
| 15 | + type = param_type(value_type) |
| 16 | + return nil if type.nil? |
| 17 | + |
| 18 | + # required properties |
| 19 | + @parsed_param = { |
| 20 | + in: type, |
| 21 | + name: settings[:full_name] || param |
| 22 | + } |
| 23 | + |
| 24 | + # optional properties |
| 25 | + document_description(settings) |
| 26 | + document_type_and_format(settings, data_type) |
| 27 | + document_array_param(value_type, definitions) if value_type[:is_array] |
| 28 | + document_default_value(settings) unless value_type[:is_array] |
| 29 | + document_range_values(settings) unless value_type[:is_array] |
| 30 | + document_required(settings) |
| 31 | + |
| 32 | + @parsed_param |
| 33 | + end |
| 34 | + |
| 35 | + private |
| 36 | + |
| 37 | + def document_description(settings) |
| 38 | + description = settings[:desc] || settings[:description] |
| 39 | + @parsed_param[:description] = description if description |
| 40 | + end |
| 41 | + |
| 42 | + def document_required(settings) |
| 43 | + @parsed_param[:required] = settings[:required] || false |
| 44 | + @parsed_param[:required] = true if @parsed_param[:in] == 'path' |
| 45 | + end |
| 46 | + |
| 47 | + def document_range_values(settings) |
| 48 | + values = settings[:values] || nil |
| 49 | + enum_or_range_values = parse_enum_or_range_values(values) |
| 50 | + @parsed_param.merge!(enum_or_range_values) if enum_or_range_values |
| 51 | + end |
| 52 | + |
| 53 | + def document_default_value(settings) |
| 54 | + @parsed_param[:default] = settings[:default] if settings[:default].present? |
| 55 | + end |
| 56 | + |
| 57 | + def document_type_and_format(settings, data_type) |
| 58 | + if DataType.primitive?(data_type) |
| 59 | + data = DataType.mapping(data_type) |
| 60 | + @parsed_param[:type], @parsed_param[:format] = data |
| 61 | + else |
| 62 | + @parsed_param[:type] = data_type |
| 63 | + end |
| 64 | + @parsed_param[:format] = settings[:format] if settings[:format].present? |
| 65 | + end |
| 66 | + |
| 67 | + def document_array_param(value_type, definitions) |
| 68 | + if value_type[:documentation].present? |
| 69 | + param_type = value_type[:documentation][:param_type] |
| 70 | + doc_type = value_type[:documentation][:type] |
| 71 | + type = DataType.mapping(doc_type) if doc_type && !DataType.request_primitive?(doc_type) |
| 72 | + collection_format = value_type[:documentation][:collectionFormat] |
| 73 | + end |
| 74 | + |
| 75 | + param_type ||= value_type[:param_type] |
| 76 | + |
| 77 | + array_items = {} |
| 78 | + if definitions[value_type[:data_type]] |
| 79 | + array_items['$ref'] = "#/definitions/#{@parsed_param[:type]}" |
| 80 | + else |
| 81 | + array_items[:type] = type || @parsed_param[:type] == 'array' ? 'string' : @parsed_param[:type] |
| 82 | + end |
| 83 | + array_items[:format] = @parsed_param.delete(:format) if @parsed_param[:format] |
| 84 | + |
| 85 | + values = value_type[:values] || nil |
| 86 | + enum_or_range_values = parse_enum_or_range_values(values) |
| 87 | + array_items.merge!(enum_or_range_values) if enum_or_range_values |
| 88 | + |
| 89 | + array_items[:default] = value_type[:default] if value_type[:default].present? |
| 90 | + |
| 91 | + @parsed_param[:in] = param_type || 'formData' |
| 92 | + @parsed_param[:items] = array_items |
| 93 | + @parsed_param[:type] = 'array' |
| 94 | + @parsed_param[:collectionFormat] = collection_format if DataType.collections.include?(collection_format) |
| 95 | + end |
| 96 | + |
| 97 | + def param_type(value_type) |
| 98 | + if value_type[:path].include?("{#{value_type[:param_name]}}") |
| 99 | + nil |
| 100 | + elsif %w[POST PUT PATCH].include?(value_type[:method]) |
| 101 | + DataType.request_primitive?(value_type[:data_type]) ? 'formData' : 'body' |
| 102 | + end |
| 103 | + end |
| 104 | + |
| 105 | + def parse_enum_or_range_values(values) |
| 106 | + case values |
| 107 | + when Proc |
| 108 | + parse_enum_or_range_values(values.call) if values.parameters.empty? |
| 109 | + when Range |
| 110 | + parse_range_values(values) if values.first.is_a?(Integer) |
| 111 | + else |
| 112 | + { enum: values } if values |
| 113 | + end |
| 114 | + end |
| 115 | + |
| 116 | + def parse_range_values(values) |
| 117 | + { minimum: values.first, maximum: values.last } |
| 118 | + end |
| 119 | + end |
| 120 | + end |
| 121 | + end |
| 122 | +end |
0 commit comments