Skip to content

Commit

Permalink
Ensure inherited nested exposures are merged (#72)
Browse files Browse the repository at this point in the history
* Ensure inherited hash exposure are merged

* Add changelog entry for #72

* Add missing period at the end of the line
  • Loading branch information
pirhoo authored May 29, 2024
1 parent 2ea7799 commit 9f44aa2
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#### Fixes

* Your contribution here.
* [#72](https://github.com/ruby-grape/grape-swagger-entity/pull/72): Ensure inherited nested exposures are merged - [@pirhoo](https://github.com/pirhoo).
* [#71](https://github.com/ruby-grape/grape-swagger-entity/pull/71): Fix regression for enum values in array attributes - [@Jell](https://github.com/Jell).

### 0.5.4 (2024/04/19)
Expand Down
23 changes: 13 additions & 10 deletions lib/grape-swagger/entity/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,19 +101,22 @@ def add_discriminator(parsed, discriminator)
end

def parse_nested(entity_name, entity_options, parent_model = nil)
nested_entity = if parent_model.nil?
model.root_exposures.find_by(entity_name)
else
parent_model.nested_exposures.find_by(entity_name)
end

params = nested_entity.nested_exposures.each_with_object({}) do |value, memo|
nested_entities = if parent_model.nil?
model.root_exposures.select_by(entity_name)
else
parent_model.nested_exposures.select_by(entity_name)
end

params = nested_entities
.map(&:nested_exposures)
.flatten
.each_with_object({}) do |value, memo|
memo[value.attribute] = value.send(:options)
end

properties, required = parse_grape_entity_params(params, nested_entity)
is_a_collection = entity_options[:documentation].is_a?(Hash) &&
entity_options[:documentation][:type].to_s.casecmp('array').zero?
properties, required = parse_grape_entity_params(params, nested_entities.last)
documentation = entity_options[:documentation]
is_a_collection = documentation.is_a?(Hash) && documentation[:type].to_s.casecmp('array').zero?

if is_a_collection
{
Expand Down
89 changes: 89 additions & 0 deletions spec/grape-swagger/entities/response_model_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,28 @@ class Nested < Grape::Entity
end
end

class NestedChild < Nested
expose :nested, documentation: { type: Hash, desc: 'Nested entity' } do
expose :some3, documentation: { type: 'String', desc: 'Nested some 3' }
end

expose :nested_with_alias, as: :aliased do
expose :some2, documentation: { type: 'String', desc: 'Alias some 2' }
end

expose :deep_nested, documentation: { type: 'Object', desc: 'Deep nested entity' } do
expose :level_1, documentation: { type: 'Object', desc: 'More deepest nested entity' } do
expose :level_2, documentation: { type: 'String', desc: 'Level 2' } do
expose :level_3, documentation: { type: 'String', desc: 'Level 3' }
end
end
end

expose :nested_array, documentation: { type: 'Array', desc: 'Nested array' } do
expose :category, documentation: { type: 'String', desc: 'Collection element category' }
end
end

class Polymorphic < Grape::Entity
expose :obj, as: :kind, if: lambda { |instance, _|
instance.type == 'kind'
Expand All @@ -162,6 +184,7 @@ class SomeEntity < Grape::Entity
documentation: { type: 'TheseApi_Relation', desc: 'A related model.' }
expose :values, using: TheseApi::Entities::Values, documentation: { desc: 'Tertiary kind.' }
expose :nested, using: TheseApi::Entities::Nested, documentation: { desc: 'Nested object.' }
expose :nested_child, using: TheseApi::Entities::NestedChild, documentation: { desc: 'Nested child object.' }
expose :polymorphic, using: TheseApi::Entities::Polymorphic, documentation: { desc: 'Polymorphic Model' }
expose :merged_attribute, using: ThisApi::Entities::Nested, merge: true
end
Expand Down Expand Up @@ -268,6 +291,70 @@ def app
},
'type' => 'object'
)
expect(subject['TheseApi_Entities_NestedChild']).to eq(
'properties' => {
'nested' => {
'type' => 'object',
'properties' => {
'some1' => { 'type' => 'string', 'description' => 'Nested some 1' },
'some2' => { 'type' => 'string', 'description' => 'Nested some 2' },
'some3' => { 'type' => 'string', 'description' => 'Nested some 3' }
},
'description' => 'Nested entity'
},
'aliased' => {
'type' => 'object',
'properties' => {
'some1' => { 'type' => 'string', 'description' => 'Alias some 1' },
'some2' => { 'type' => 'string', 'description' => 'Alias some 2' }
}
},
'deep_nested' => {
'type' => 'object',
'properties' => {
'level_1' => {
'type' => 'object',
'properties' => {
'level_2' => {
'type' => 'object',
'properties' => {
'level_3' => {
'type' => 'string',
'description' => 'Level 3'
}
},
'description' => 'Level 2'
}
},
'description' => 'More deepest nested entity'
}
},
'description' => 'Deep nested entity'
},
'nested_required' => {
'type' => 'object',
'properties' => {
'some1' => { 'type' => 'string', 'description' => 'Required some 1' },
'some2' => { 'type' => 'string', 'description' => 'Required some 2' },
'some3' => { 'type' => 'string', 'description' => 'Optional some 3' }
},
'required' => %w[some1 some2]
},
'nested_array' => {
'type' => 'array',
'items' => {
'type' => 'object',
'properties' => {
'id' => { 'type' => 'integer', 'format' => 'int32', 'description' => 'Collection element id' },
'name' => { 'type' => 'string', 'description' => 'Collection element name' },
'category' => { 'type' => 'string', 'description' => 'Collection element category' }
}
},
'description' => 'Nested array'
}
},
'type' => 'object'
)
expect(subject['TheseApi_Entities_Polymorphic']).to eql(
'type' => 'object',
'properties' => {
Expand All @@ -290,6 +377,8 @@ def app
'relation' => { '$ref' => '#/definitions/TheseApi_Entities_Relation', 'description' => 'A related model.' },
'values' => { '$ref' => '#/definitions/TheseApi_Entities_Values', 'description' => 'Tertiary kind.' },
'nested' => { '$ref' => '#/definitions/TheseApi_Entities_Nested', 'description' => 'Nested object.' },
'nested_child' => { '$ref' => '#/definitions/TheseApi_Entities_NestedChild',
'description' => 'Nested child object.' },
'code' => { 'type' => 'string', 'description' => 'Error code' },
'message' => { 'type' => 'string', 'description' => 'Error message' },
'polymorphic' => { '$ref' => '#/definitions/TheseApi_Entities_Polymorphic',
Expand Down

0 comments on commit 9f44aa2

Please sign in to comment.