diff --git a/CHANGELOG.md b/CHANGELOG.md index 28d5830..b4e0b3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ #### Features -* Your contribution here. +* [#33](https://github.com/ruby-grape/grape-swagger-entity/pull/33): Update parser to respect merge option for entities - [@b-boogaard](https://github.com/b-boogaard). #### Fixes diff --git a/lib/grape-swagger/entity/parser.rb b/lib/grape-swagger/entity/parser.rb index 105cdc5..7527110 100644 --- a/lib/grape-swagger/entity/parser.rb +++ b/lib/grape-swagger/entity/parser.rb @@ -12,15 +12,23 @@ def initialize(model, endpoint) end def call - parameters = model.root_exposures.each_with_object({}) do |value, memo| - memo[value.attribute] = value.send(:options) - end - - parse_grape_entity_params(parameters) + parse_grape_entity_params(extract_params(model)) end private + def extract_params(exposure) + exposure.root_exposures.each_with_object({}) do |value, memo| + if value.for_merge && (value.respond_to?(:entity_class) || value.respond_to?(:using_class_name)) + entity_class = value.respond_to?(:entity_class) ? value.entity_class : value.using_class_name + + memo.merge!(extract_params(entity_class)) + else + memo[value.attribute] = value.send(:options) + end + end + end + def parse_grape_entity_params(params, parent_model = nil) return unless params diff --git a/spec/grape-swagger/entities/response_model_spec.rb b/spec/grape-swagger/entities/response_model_spec.rb index b9c9b63..ef4c24d 100644 --- a/spec/grape-swagger/entities/response_model_spec.rb +++ b/spec/grape-swagger/entities/response_model_spec.rb @@ -56,7 +56,10 @@ def app 'kind2' => { '$ref' => '#/definitions/Kind', 'description' => 'Secondary kind.' }, 'kind3' => { '$ref' => '#/definitions/Kind', 'description' => 'Tertiary kind.' }, 'tags' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/Tag' }, 'description' => 'Tags.' }, - 'relation' => { '$ref' => '#/definitions/Relation', 'description' => 'A related model.' } } + 'relation' => { '$ref' => '#/definitions/Relation', 'description' => 'A related model.' }, + 'code' => { 'type' => 'string', 'description' => 'Error code' }, + 'message' => { 'type' => 'string', 'description' => 'Error message' }, + 'attr' => { 'type' => 'string', 'description' => 'Attribute' } } ) expect(subject['definitions'].keys).to include 'Kind' @@ -134,6 +137,7 @@ class SomeEntity < Grape::Entity expose :relation, using: TheseApi::Entities::Relation, 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 :merged_attribute, using: ThisApi::Entities::Nested, merge: true end end @@ -246,7 +250,10 @@ def app 'tags' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/Tag' }, 'description' => 'Tags.' }, 'relation' => { '$ref' => '#/definitions/Relation', 'description' => 'A related model.' }, 'values' => { '$ref' => '#/definitions/Values', 'description' => 'Tertiary kind.' }, - 'nested' => { '$ref' => '#/definitions/Nested', 'description' => 'Nested object.' } + 'nested' => { '$ref' => '#/definitions/Nested', 'description' => 'Nested object.' }, + 'code' => { 'type' => 'string', 'description' => 'Error code' }, + 'message' => { 'type' => 'string', 'description' => 'Error message' }, + 'attr' => { 'type' => 'string', 'description' => 'Attribute' } }, 'description' => 'This returns something' ) diff --git a/spec/grape-swagger/entity/parser_spec.rb b/spec/grape-swagger/entity/parser_spec.rb index 86e6b53..814cd3b 100644 --- a/spec/grape-swagger/entity/parser_spec.rb +++ b/spec/grape-swagger/entity/parser_spec.rb @@ -15,6 +15,13 @@ expect(parsed_entity[:kind2]['$ref']).to eq('#/definitions/Kind') expect(parsed_entity[:kind3]['$ref']).to eq('#/definitions/Kind') end + + it 'merges attributes that have merge: true defined' do + expect(parsed_entity[:merged_attribute]).to be_nil + expect(parsed_entity[:code][:type]).to eq('string') + expect(parsed_entity[:message][:type]).to eq('string') + expect(parsed_entity[:attr][:type]).to eq('string') + end end end end diff --git a/spec/support/shared_contexts/this_api.rb b/spec/support/shared_contexts/this_api.rb index fd726b5..cc7035d 100644 --- a/spec/support/shared_contexts/this_api.rb +++ b/spec/support/shared_contexts/this_api.rb @@ -17,6 +17,11 @@ class Error < Grape::Entity expose :message, documentation: { type: 'string', desc: 'Error message' } end + class Nested < Grape::Entity + expose :attr, documentation: { type: 'string', desc: 'Attribute' } + expose :nested_attrs, merge: true, using: ThisApi::Entities::Error + end + class Something < Grape::Entity expose :text, documentation: { type: 'string', desc: 'Content of something.' } expose :colors, documentation: { type: 'string', desc: 'Colors', is_array: true } @@ -25,6 +30,7 @@ class Something < Grape::Entity expose :kind3, using: ThisApi::Entities::Kind, documentation: { desc: 'Tertiary kind.' } expose :tags, using: ThisApi::Entities::Tag, documentation: { desc: 'Tags.', is_array: true } expose :relation, using: ThisApi::Entities::Relation, documentation: { type: 'ThisApi::Relation', desc: 'A related model.' } + expose :merged_attribute, using: ThisApi::Entities::Nested, merge: true end end