Skip to content

Commit 0c1af79

Browse files
authored
Fix handling of entity with class names without "Entity" or "Entities" (#75)
1 parent d877ea5 commit 0c1af79

File tree

7 files changed

+87
-7
lines changed

7 files changed

+87
-7
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
strategy:
3131
fail-fast: false
3232
matrix:
33-
ruby-version: ['3.0', '3.1', '3.2', '3.3']
33+
ruby-version: ['3.1', '3.2', '3.3']
3434

3535
steps:
3636
- uses: actions/checkout@v4

.rubocop_todo.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ RSpec/DescribeClass:
100100
# Offense count: 4
101101
# Configuration parameters: CountAsOne.
102102
RSpec/ExampleLength:
103-
Max: 172
103+
Max: 186
104104

105105
# Offense count: 24
106106
RSpec/LeakyConstantDeclaration:

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#### Fixes
88

99
* Your contribution here.
10+
* [#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).
1011

1112
### 0.5.5 (2024/09/09)
1213

lib/grape-swagger/entity/attribute_parser.rb

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ module Entity
55
class AttributeParser
66
attr_reader :endpoint
77

8+
# The list of that doesn't handled by `GrapeSwagger::DocMethods::DataType.primitive?` method
9+
ADDITIONAL_PRIMITIVE_TYPES = %w[string array].freeze
10+
811
def initialize(endpoint)
912
@endpoint = endpoint
1013
end
@@ -53,9 +56,15 @@ def direct_model_type?(type)
5356
end
5457

5558
def ambiguous_model_type?(type)
56-
type&.is_a?(Class) &&
57-
!GrapeSwagger::DocMethods::DataType.primitive?(type.name.downcase) &&
58-
!type == Array
59+
type&.is_a?(Class) && !primitive_type?(type)
60+
end
61+
62+
def primitive_type?(type)
63+
type_name = type.name&.downcase
64+
return false if type_name.nil?
65+
66+
GrapeSwagger::DocMethods::DataType.primitive?(type_name) ||
67+
ADDITIONAL_PRIMITIVE_TYPES.include?(type_name)
5968
end
6069

6170
def data_type_from(entity_options)

spec/grape-swagger/entities/response_model_spec.rb

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,16 @@ class Polymorphic < Grape::Entity
179179
}, documentation: { desc: 'Polymorphic Number', type: 'Integer' }
180180
end
181181

182+
class TagType < CustomType
183+
def tags
184+
%w[Cyan Magenta Yellow Key]
185+
end
186+
end
187+
188+
class MixedType < Grape::Entity
189+
expose :tags, documentation: { type: TagType, desc: 'Tags', is_array: true }
190+
end
191+
182192
class SomeEntity < Grape::Entity
183193
expose :text, documentation: { type: 'string', desc: 'Content of something.' }
184194
expose :kind, using: Kind, documentation: { type: 'TheseApi_Kind', desc: 'The kind of this something.' }
@@ -190,7 +200,8 @@ class SomeEntity < Grape::Entity
190200
expose :values, using: TheseApi::Entities::Values, documentation: { desc: 'Tertiary kind.' }
191201
expose :nested, using: TheseApi::Entities::Nested, documentation: { desc: 'Nested object.' }
192202
expose :nested_child, using: TheseApi::Entities::NestedChild, documentation: { desc: 'Nested child object.' }
193-
expose :polymorphic, using: TheseApi::Entities::Polymorphic, documentation: { desc: 'Polymorphic Model' }
203+
expose :polymorphic, using: TheseApi::Entities::Polymorphic, documentation: { desc: 'A polymorphic model.' }
204+
expose :mixed, using: TheseApi::Entities::MixedType, documentation: { desc: 'A model with mix of types.' }
194205
expose :merged_attribute, using: ThisApi::Entities::Nested, merge: true
195206
end
196207
end
@@ -365,6 +376,17 @@ def app
365376
}
366377
)
367378

379+
expect(subject['TheseApi_Entities_MixedType']).to eql(
380+
'properties' => {
381+
'tags' => {
382+
'description' => 'Tags',
383+
'items' => { '$ref' => '#/definitions/TheseApi_Entities_TagType' },
384+
'type' => 'array'
385+
}
386+
},
387+
'type' => 'object'
388+
)
389+
368390
expect(subject['TheseApi_Entities_SomeEntity']).to eql(
369391
'type' => 'object',
370392
'properties' => {
@@ -382,7 +404,11 @@ def app
382404
'code' => { 'type' => 'string', 'description' => 'Error code' },
383405
'message' => { 'type' => 'string', 'description' => 'Error message' },
384406
'polymorphic' => { '$ref' => '#/definitions/TheseApi_Entities_Polymorphic',
385-
'description' => 'Polymorphic Model' },
407+
'description' => 'A polymorphic model.' },
408+
'mixed' => {
409+
'$ref' => '#/definitions/TheseApi_Entities_MixedType',
410+
'description' => 'A model with mix of types.'
411+
},
386412
'attr' => { 'type' => 'string', 'description' => 'Attribute' }
387413
},
388414
'required' => %w[attr],

spec/grape-swagger/entity/attribute_parser_spec.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,24 @@
3535
it { is_expected.to include(example: %w[green blue].map { { name: _1 } }) }
3636
end
3737

38+
context 'when the entity is implicit Entity' do
39+
let(:entity_type) do
40+
Class.new(ThisApi::Entities::Tag) do
41+
def self.name
42+
'ThisApi::Tag'
43+
end
44+
45+
def self.to_s
46+
name
47+
end
48+
end
49+
end
50+
let(:entity_options) { { documentation: { type: entity_type, is_array: true, min_items: 1 } } }
51+
52+
it { is_expected.to include('type' => 'array') }
53+
it { is_expected.to include('items' => { '$ref' => '#/definitions/Tag' }) }
54+
end
55+
3856
context 'when it contains min_items' do
3957
let(:entity_options) { { using: ThisApi::Entities::Tag, documentation: { is_array: true, min_items: 1 } } }
4058

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# frozen_string_literal: true
2+
3+
CustomType = Class.new
4+
5+
class CustomTypeParser
6+
attr_reader :model, :endpoint
7+
8+
def initialize(model, endpoint)
9+
@model = model
10+
@endpoint = endpoint
11+
end
12+
13+
def call
14+
{
15+
model.name.to_sym => {
16+
type: 'custom_type',
17+
description: "it's a custom type",
18+
data: {
19+
name: model.name
20+
}
21+
}
22+
}
23+
end
24+
end
25+
26+
GrapeSwagger.model_parsers.register(CustomTypeParser, CustomType)

0 commit comments

Comments
 (0)