Skip to content

Commit

Permalink
Fix handling of entity with class names without "Entity" or "Entities" (
Browse files Browse the repository at this point in the history
  • Loading branch information
numbata authored Jan 30, 2025
1 parent d877ea5 commit 0c1af79
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 7 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
strategy:
fail-fast: false
matrix:
ruby-version: ['3.0', '3.1', '3.2', '3.3']
ruby-version: ['3.1', '3.2', '3.3']

steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion .rubocop_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ RSpec/DescribeClass:
# Offense count: 4
# Configuration parameters: CountAsOne.
RSpec/ExampleLength:
Max: 172
Max: 186

# Offense count: 24
RSpec/LeakyConstantDeclaration:
Expand Down
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.
* [#75](https://github.com/ruby-grape/grape-swagger-entity/pull/75): Fix handling of entity with class names without "entity" or "entities" - [@numbata](https://github.com/numbata).

### 0.5.5 (2024/09/09)

Expand Down
15 changes: 12 additions & 3 deletions lib/grape-swagger/entity/attribute_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ module Entity
class AttributeParser
attr_reader :endpoint

# The list of that doesn't handled by `GrapeSwagger::DocMethods::DataType.primitive?` method
ADDITIONAL_PRIMITIVE_TYPES = %w[string array].freeze

def initialize(endpoint)
@endpoint = endpoint
end
Expand Down Expand Up @@ -53,9 +56,15 @@ def direct_model_type?(type)
end

def ambiguous_model_type?(type)
type&.is_a?(Class) &&
!GrapeSwagger::DocMethods::DataType.primitive?(type.name.downcase) &&
!type == Array
type&.is_a?(Class) && !primitive_type?(type)
end

def primitive_type?(type)
type_name = type.name&.downcase
return false if type_name.nil?

GrapeSwagger::DocMethods::DataType.primitive?(type_name) ||
ADDITIONAL_PRIMITIVE_TYPES.include?(type_name)
end

def data_type_from(entity_options)
Expand Down
30 changes: 28 additions & 2 deletions spec/grape-swagger/entities/response_model_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,16 @@ class Polymorphic < Grape::Entity
}, documentation: { desc: 'Polymorphic Number', type: 'Integer' }
end

class TagType < CustomType
def tags
%w[Cyan Magenta Yellow Key]
end
end

class MixedType < Grape::Entity
expose :tags, documentation: { type: TagType, desc: 'Tags', is_array: true }
end

class SomeEntity < Grape::Entity
expose :text, documentation: { type: 'string', desc: 'Content of something.' }
expose :kind, using: Kind, documentation: { type: 'TheseApi_Kind', desc: 'The kind of this something.' }
Expand All @@ -190,7 +200,8 @@ class SomeEntity < Grape::Entity
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 :polymorphic, using: TheseApi::Entities::Polymorphic, documentation: { desc: 'A polymorphic model.' }
expose :mixed, using: TheseApi::Entities::MixedType, documentation: { desc: 'A model with mix of types.' }
expose :merged_attribute, using: ThisApi::Entities::Nested, merge: true
end
end
Expand Down Expand Up @@ -365,6 +376,17 @@ def app
}
)

expect(subject['TheseApi_Entities_MixedType']).to eql(
'properties' => {
'tags' => {
'description' => 'Tags',
'items' => { '$ref' => '#/definitions/TheseApi_Entities_TagType' },
'type' => 'array'
}
},
'type' => 'object'
)

expect(subject['TheseApi_Entities_SomeEntity']).to eql(
'type' => 'object',
'properties' => {
Expand All @@ -382,7 +404,11 @@ def app
'code' => { 'type' => 'string', 'description' => 'Error code' },
'message' => { 'type' => 'string', 'description' => 'Error message' },
'polymorphic' => { '$ref' => '#/definitions/TheseApi_Entities_Polymorphic',
'description' => 'Polymorphic Model' },
'description' => 'A polymorphic model.' },
'mixed' => {
'$ref' => '#/definitions/TheseApi_Entities_MixedType',
'description' => 'A model with mix of types.'
},
'attr' => { 'type' => 'string', 'description' => 'Attribute' }
},
'required' => %w[attr],
Expand Down
18 changes: 18 additions & 0 deletions spec/grape-swagger/entity/attribute_parser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,24 @@
it { is_expected.to include(example: %w[green blue].map { { name: _1 } }) }
end

context 'when the entity is implicit Entity' do
let(:entity_type) do
Class.new(ThisApi::Entities::Tag) do
def self.name
'ThisApi::Tag'
end

def self.to_s
name
end
end
end
let(:entity_options) { { documentation: { type: entity_type, is_array: true, min_items: 1 } } }

it { is_expected.to include('type' => 'array') }
it { is_expected.to include('items' => { '$ref' => '#/definitions/Tag' }) }
end

context 'when it contains min_items' do
let(:entity_options) { { using: ThisApi::Entities::Tag, documentation: { is_array: true, min_items: 1 } } }

Expand Down
26 changes: 26 additions & 0 deletions spec/support/shared_contexts/custom_type_parser.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true

CustomType = Class.new

class CustomTypeParser
attr_reader :model, :endpoint

def initialize(model, endpoint)
@model = model
@endpoint = endpoint
end

def call
{
model.name.to_sym => {
type: 'custom_type',
description: "it's a custom type",
data: {
name: model.name
}
}
}
end
end

GrapeSwagger.model_parsers.register(CustomTypeParser, CustomType)

0 comments on commit 0c1af79

Please sign in to comment.