66module Api
77 # Represents a group of parameters of an object within a request or response body
88 class BodyParameterGroup
9- def self . from_schema ( schema , description :, ancestors :)
10- is_array = schema . type == 'array' || schema . items . present?
11- parameters = BodyParameter . from_schema ( is_array ? schema . items : schema )
12- new ( parameters :, ancestors :, description :, is_array :)
13- end
14-
15- attr_reader :parameters , :ancestors , :description , :is_array
9+ attr_reader :members , :ancestors , :description , :is_array , :is_nested , :schema
1610
17- # @param [Array<Api::BodyParameter>] parameters
11+ # @param [SpecHash] schema schema of an object or an array of objects
1812 # @param [Array<String>] ancestors
1913 # @param [String] description
20- # @param [Boolean] is_array
21- def initialize ( parameters :, ancestors :, description :, is_array :)
22- @parameters = parameters
14+ def initialize ( schema :, ancestors :, description :)
2315 @ancestors = ancestors
2416 @description = description
25- @is_array = is_array
26- parameters . each { |param | param . group = self }
17+ @is_array = schema . items . present?
18+ @schema = @is_array ? schema . items : schema
19+ @schema = flatten_schema ( @schema )
20+ @members = parse_members ( @schema )
21+ @is_nested = @members . any? { |param | param . is_a? ( BodyParameterGroup ) }
22+ members . each { |param | param . group = self } unless @is_nested
2723 end
2824
2925 # @return [Array<BodyParameterGroup>] The child groups of the group
30- def descendants
31- @parameters . map ( &:child_params_group ) . compact . flat_map do |group |
32- [ group ] + group . descendants
26+ def descendants ( seen_schemas = Set . new ( [ @schema ] ) )
27+ child_groups = @is_nested ? @members : @members . map ( &:child_params_group ) . compact
28+ child_groups . reject { |g | seen_schemas . include? ( g . schema ) } . flat_map do |group |
29+ seen_schemas . add ( group . schema )
30+ [ group ] + group . descendants ( seen_schemas )
3331 end
3432 end
35- end
3633
37- # TODO: Handle cyclic references
38- # Represents a body parameter of different levels of a request or response body
39- class BodyParameter < Parameter
40- # @param [SpecHash] schema The schema of an object
41- # @return [Array<Api::BodyParameter>] The parameters of the object
42- def self . from_schema ( schema )
34+ # @param [SpecHash] schema
35+ # @return [Array<Api::BodyParameter>, Array<Api::BodyParameterGroup] members
36+ def parse_members ( schema )
37+ union = schema . anyOf || schema . oneOf
38+ if union . present?
39+ return union . map { |sch | BodyParameterGroup . new ( schema : sch , ancestors : @ancestors , description :) }
40+ end
4341 properties = schema . properties || { }
4442 parameters = properties . map do |name , prop |
4543 BodyParameter . new ( name :, schema : prop , required : schema . required &.include? ( name ) )
4644 end . sort { |a , b | a . name <=> b . name }
4745 return parameters unless schema . additionalProperties
48- additional_schema = schema . additionalProperties == true ? { } : schema . additionalProperties
46+ additional_schema = schema . additionalProperties == true ? SpecHash . new ( { } ) : schema . additionalProperties
4947 free_form_name = CONFIG . param_table . parameter_column . freeform_text
50- parameters + [ BodyParameter . new ( name : free_form_name , schema : SpecHash . new ( additional_schema ) ) ]
48+ parameters + [ BodyParameter . new ( name : free_form_name , schema : additional_schema ) ]
49+ end
50+
51+ # @param [SpecHash] schema
52+ # @return [SpecHash] a schema with allOf flattened
53+ def flatten_schema ( schema )
54+ return schema if schema . allOf . blank?
55+
56+ schema = schema . allOf . each_with_object ( { 'properties' => { } , 'required' => [ ] } ) do |sch , h |
57+ sch = flatten_schema ( sch )
58+ h [ 'properties' ] . merge! ( sch . properties || { } )
59+ h [ 'required' ] += sch . required || [ ]
60+ h [ 'additionalProperties' ] ||= sch . additionalProperties
61+ end
62+
63+ SpecHash . new ( schema , fully_parsed : true )
5164 end
65+ end
5266
67+ # TODO: Handle cyclic references
68+ # Represents a body parameter of different levels of a request or response body
69+ class BodyParameter < Parameter
5370 attr_accessor :group
5471
5572 # @param [String] name
@@ -67,12 +84,12 @@ def initialize(name:, schema:, required: false)
6784 @include_object = @doc_type . include? ( 'Object' )
6885 end
6986
70- # @return [BodyParameterGroup, nil] The parameters of the object
87+ # @return [BodyParameterGroup, nil] The parameters group of an object parameter
7188 def child_params_group
7289 return nil unless @include_object
7390 return @child_params_group if defined? ( @child_params_group )
74- @child_params_group ||= BodyParameterGroup . from_schema (
75- @schema ,
91+ @child_params_group ||= BodyParameterGroup . new (
92+ schema : @schema ,
7693 ancestors : @group . ancestors + [ @name ] ,
7794 description : @description
7895 )
@@ -82,6 +99,7 @@ def child_params_group
8299
83100 # TODO: Turn this into a configurable setting
84101 def parse_array ( schema )
102+ return 'Array' if schema . items == true || schema . items . nil?
85103 "Array of #{ parse_doc_type ( schema . items ) . pluralize } "
86104 end
87105 end
0 commit comments