diff --git a/lib/rspec/openapi/components_updater.rb b/lib/rspec/openapi/components_updater.rb index 8839d6b1..b53b63d7 100644 --- a/lib/rspec/openapi/components_updater.rb +++ b/lib/rspec/openapi/components_updater.rb @@ -13,9 +13,14 @@ def update!(base, fresh) generated_schema_names = fresh_schemas.keys nested_refs = find_non_top_level_nested_refs(base, generated_schema_names) nested_refs.each do |paths| - parent_name = paths[-4] - property_name = paths[-2] - nested_schema = fresh_schemas.dig(parent_name, 'properties', property_name) + # Slice between the parent name and the element before "$ref" + # [..., "Table", "properties", "database", "$ref"] + # ^idx-1 ^idx ^size-idx + # [..., "Table", "properties", "columns", "items", "$ref"] + # ^idx-1 ^idx ^size-idx + idx_properties = paths.size - 1 - paths.reverse.find_index('properties') + needle = paths.slice(idx_properties - 1, paths.size - idx_properties) + nested_schema = fresh_schemas.dig(*needle) # Skip if the property using $ref is not found in the parent schema. The property may be removed. next if nested_schema.nil? @@ -53,8 +58,10 @@ def paths_to_top_level_refs(base) end def find_non_top_level_nested_refs(base, generated_names) - nested_refs = RSpec::OpenAPI::HashHelper::matched_paths(base, 'components.schemas.*.properties.*.$ref') - + nested_refs = [ + *RSpec::OpenAPI::HashHelper.matched_paths(base, 'components.schemas.*.properties.*.$ref'), + *RSpec::OpenAPI::HashHelper.matched_paths(base, 'components.schemas.*.properties.*.*.$ref') + ] # Reject already-generated schemas to reduce unnecessary loop nested_refs.reject do |paths| ref_link = base.dig(*paths) diff --git a/spec/rails/app/controllers/tables_controller.rb b/spec/rails/app/controllers/tables_controller.rb index f43daa1c..a74d4e69 100644 --- a/spec/rails/app/controllers/tables_controller.rb +++ b/spec/rails/app/controllers/tables_controller.rb @@ -5,7 +5,11 @@ class TablesController < ApplicationController def index response.set_header('X-Cursor', 100) - render json: [find_table] + if params[:show_columns] + render json: [find_table('42')] + else + render json: [find_table] + end end def show @@ -53,6 +57,24 @@ def find_table(id = nil) created_at: time.iso8601, updated_at: time.iso8601, } + when '42' + { + id: 42, + name: 'access', + description: 'logs', + database: { + id: 4242, + name: 'production' + }, + columns: [ + { name: 'id', column_type: 'integer' }, + { name: 'description', column_type: 'varchar' } + ], + null_sample: nil, + storage_size: 12.3, + created_at: time.iso8601, + updated_at: time.iso8601, + } else raise NotFoundError end diff --git a/spec/rails/doc/smart/expected.yaml b/spec/rails/doc/smart/expected.yaml index dce47efd..e8b0bf64 100644 --- a/spec/rails/doc/smart/expected.yaml +++ b/spec/rails/doc/smart/expected.yaml @@ -36,6 +36,11 @@ paths: schema: type: integer example: 10 + - name: show_columns + in: query + schema: + type: string + example: "true" responses: '200': description: with flat query parameters @@ -46,16 +51,21 @@ paths: items: "$ref": "#/components/schemas/Table" example: - - id: 1 + - id: 42 name: access description: logs database: - id: 2 + id: 4242 name: production null_sample: storage_size: 12.3 created_at: '2020-07-17T00:00:00+00:00' updated_at: '2020-07-17T00:00:00+00:00' + columns: + - name: id + column_type: integer + - name: description + column_type: varchar headers: X-Cursor: schema: @@ -137,6 +147,10 @@ components: type: string database: "$ref": "#/components/schemas/Database" + columns: + type: array + items: + "$ref": "#/components/schemas/Column" null_sample: nullable: true storage_size: @@ -155,3 +169,10 @@ components: description: 'this should be preserved' name: type: string + Column: + type: object + properties: + name: + type: string + column_type: + type: string diff --git a/spec/rails/doc/smart/openapi.yaml b/spec/rails/doc/smart/openapi.yaml index c608b5da..a4ed6de7 100644 --- a/spec/rails/doc/smart/openapi.yaml +++ b/spec/rails/doc/smart/openapi.yaml @@ -214,6 +214,10 @@ components: type: string database: "$ref": "#/components/schemas/Database" + columns: + type: array + items: + "$ref": "#/components/schemas/Column" null_sample: nullable: true storage_size: diff --git a/spec/requests/rails_smart_merge_spec.rb b/spec/requests/rails_smart_merge_spec.rb index 5d19b8d1..0cf1d20e 100644 --- a/spec/requests/rails_smart_merge_spec.rb +++ b/spec/requests/rails_smart_merge_spec.rb @@ -29,7 +29,7 @@ context it 'returns a list of tables' do it 'with flat query parameters' do # These new params replace them in old spec - get '/tables', params: { page: '42', per: '10' }, + get '/tables', params: { page: '42', per: '10', show_columns: true }, headers: { authorization: 'k0kubun', "X-Authorization-Token": 'token' } response.set_header('X-Cursor', 100) expect(response.status).to eq(200)