grape-swagger 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: beb6baac3bba57a4fd27f01c8129fbd128c0c88426f1408784f1e77ef870c65a
4
- data.tar.gz: 88234909ace085c8b63f0534630ae8856eb15d383bee856c9fcc57079d0060a1
3
+ metadata.gz: eae164875a188218b1eb4e0e3a53039f8e661f3dd115b4cc9a6f415b3a92e64b
4
+ data.tar.gz: 6962782ea370ff7b4f84c62ed77f2fe1e7232332f3a238bce4c5af5b62eb1534
5
5
  SHA512:
6
- metadata.gz: 3b50e2b60fb3d4a1876bac4587f740c27a624c02726153746dc79e76fb1a233d04a3b1b15844bf65a337484d551ac6ea84b04c85c1537138dfc4327149cbb654
7
- data.tar.gz: 32a0e9014bf782a0f5a5417a307bf9325986d7d9df662e73174525792e9103d2a3ec3c4f8b3d7fbdc72829d7514ba299dd62adb361085020f37b104f9a29ee25
6
+ metadata.gz: 8b56b026ba97a2308579737c43daf0e9f619df0c91c511e424b533f99105faec83f9ddbcb3dd2f3d98866bffdbdecb13e652f302424f54ec4095c4605405319c
7
+ data.tar.gz: 2e88c630ade44d4c9395a18e690cad717f5a6ba6e6daae81624d0b7e6347f06c9d7d07ce85f16b5eb99ea25c1a716127cd8aac17c1367823ded3bd84151dbc47
@@ -11,6 +11,9 @@ AllCops:
11
11
  Layout/EmptyLinesAroundArguments:
12
12
  Enabled: false
13
13
 
14
+ Layout/EmptyLinesAroundAttributeAccessor:
15
+ Enabled: true
16
+
14
17
  Layout/FirstHashElementIndentation:
15
18
  EnforcedStyle: consistent
16
19
 
@@ -24,6 +27,12 @@ Layout/SpaceAroundMethodCallOperator:
24
27
 
25
28
  # Lint stuff
26
29
  #
30
+ Lint/DeprecatedOpenSSLConstant:
31
+ Enabled: true
32
+
33
+ Lint/MixedRegexpCaptureTypes:
34
+ Enabled: true
35
+
27
36
  Lint/RaiseException:
28
37
  Enabled: true
29
38
 
@@ -39,6 +48,9 @@ Metrics/BlockLength:
39
48
  Metrics/ClassLength:
40
49
  Max: 300
41
50
 
51
+ Metrics/CyclomaticComplexity:
52
+ Max: 17
53
+
42
54
  Metrics/MethodLength:
43
55
  Exclude:
44
56
  - spec/**/*
@@ -64,3 +76,15 @@ Style/HashTransformValues:
64
76
 
65
77
  Style/RegexpLiteral:
66
78
  Enabled: false
79
+
80
+ Style/RedundantFetchBlock:
81
+ Enabled: true
82
+
83
+ Style/RedundantRegexpCharacterClass:
84
+ Enabled: true
85
+
86
+ Style/RedundantRegexpEscape:
87
+ Enabled: true
88
+
89
+ Style/SlicingWithRange:
90
+ Enabled: false
@@ -33,3 +33,5 @@ jobs:
33
33
  - rvm: 2.4.10
34
34
  - rvm: ruby-head
35
35
  - rvm: jruby-head
36
+
37
+ - env: GRAPE_VERSION=HEAD
@@ -9,6 +9,19 @@
9
9
  * Your contribution here.
10
10
 
11
11
 
12
+ ### 1.2.0 (July 1, 2020)
13
+
14
+ #### Features
15
+
16
+ * [#794](https://github.com/ruby-grape/grape-swagger/pull/794): Allow `entity_name` to be inherited, fixes issue #659 - [@urkle](https://github.com/urkle).
17
+ * [#793](https://github.com/ruby-grape/grape-swagger/pull/793): Features/inheritance and discriminator - [@MaximeRDY](https://github.com/MaximeRDY).
18
+
19
+ #### Fixes
20
+
21
+ * [#798](https://github.com/ruby-grape/grape-swagger/pull/798): Modify full entity name separator - [@GarrettB71](https://github.com/GarrettB71).
22
+ * [#796](https://github.com/ruby-grape/grape-swagger/pull/796): Support grape 1.4.0 - [@thedanielhanke](https://github.com/thedanielhanke).
23
+
24
+
12
25
  ### 1.1.0 (April 20, 2020)
13
26
 
14
27
  #### Features
data/Gemfile CHANGED
@@ -14,6 +14,7 @@ gem 'grape', case version = ENV['GRAPE_VERSION'] || '>= 1.3.0'
14
14
  end
15
15
 
16
16
  gem ENV['MODEL_PARSER'] if ENV.key?('MODEL_PARSER')
17
+
17
18
  group :development, :test do
18
19
  gem 'bundler'
19
20
  gem 'grape-entity'
@@ -26,12 +27,16 @@ group :development, :test do
26
27
  gem 'rake'
27
28
  gem 'rdoc'
28
29
  gem 'rspec', '~> 3.9'
29
- gem 'rubocop', '~> 0.82', require: false
30
+ gem 'rubocop', '~> 0.85', require: false
30
31
  end
31
32
 
32
33
  group :test do
33
34
  gem 'coveralls_reborn', require: false
34
- gem 'grape-swagger-entity'
35
+
35
36
  gem 'ruby-grape-danger', '~> 0.1.1', require: false
36
37
  gem 'simplecov', require: false
38
+
39
+ unless ENV['MODEL_PARSER'] == 'grape-swagger-entity'
40
+ gem 'grape-swagger-entity', git: 'https://github.com/ruby-grape/grape-swagger-entity'
41
+ end
37
42
  end
data/README.md CHANGED
@@ -43,16 +43,16 @@ This screenshot is based on the [Hussars](https://github.com/LeFnord/hussars) sa
43
43
 
44
44
  The following versions of grape, grape-entity and grape-swagger can currently be used together.
45
45
 
46
- grape-swagger | swagger spec | grape | grape-entity | representable |
47
- --------------|--------------|-------------------------|--------------|---------------|
48
- 0.10.5 | 1.2 | >= 0.10.0 ... <= 0.14.0 | < 0.5.0 | n/a |
49
- 0.11.0 | 1.2 | >= 0.16.2 | < 0.5.0 | n/a |
50
- 0.25.2 | 2.0 | >= 0.14.0 ... <= 0.18.0 | <= 0.6.0 | >= 2.4.1 |
51
- 0.26.0 | 2.0 | >= 0.16.2 ... <= 1.1.0 | <= 0.6.1 | >= 2.4.1 |
52
- 0.27.0 | 2.0 | >= 0.16.2 ... <= 1.1.0 | >= 0.5.0 | >= 2.4.1 |
53
- 0.32.0 | 2.0 | >= 0.16.2 | >= 0.5.0 | >= 2.4.1 |
54
- 0.34.0 | 2.0 | >= 0.16.2 ... < 1.3.0 | >= 0.5.0 | >= 2.4.1 |
55
- >= 1.0.0 | 2.0 | >= 1.3.0 | >= 0.5.0 | >= 2.4.1 |
46
+ | grape-swagger | swagger spec | grape | grape-entity | representable |
47
+ | ------------- | ------------ | ----------------------- | ------------ | ------------- |
48
+ | 0.10.5 | 1.2 | >= 0.10.0 ... <= 0.14.0 | < 0.5.0 | n/a |
49
+ | 0.11.0 | 1.2 | >= 0.16.2 | < 0.5.0 | n/a |
50
+ | 0.25.2 | 2.0 | >= 0.14.0 ... <= 0.18.0 | <= 0.6.0 | >= 2.4.1 |
51
+ | 0.26.0 | 2.0 | >= 0.16.2 ... <= 1.1.0 | <= 0.6.1 | >= 2.4.1 |
52
+ | 0.27.0 | 2.0 | >= 0.16.2 ... <= 1.1.0 | >= 0.5.0 | >= 2.4.1 |
53
+ | 0.32.0 | 2.0 | >= 0.16.2 | >= 0.5.0 | >= 2.4.1 |
54
+ | 0.34.0 | 2.0 | >= 0.16.2 ... < 1.3.0 | >= 0.5.0 | >= 2.4.1 |
55
+ | >= 1.0.0 | 2.0 | >= 1.3.0 | >= 0.5.0 | >= 2.4.1 |
56
56
 
57
57
 
58
58
  ## Swagger-Spec <a name="swagger-spec"></a>
@@ -1381,6 +1381,94 @@ module API
1381
1381
  end
1382
1382
  ```
1383
1383
 
1384
+ #### Inheritance with allOf and discriminator
1385
+ ```ruby
1386
+ module Entities
1387
+ class Pet < Grape::Entity
1388
+ expose :type, documentation: {
1389
+ type: 'string',
1390
+ is_discriminator: true,
1391
+ required: true
1392
+ }
1393
+ expose :name, documentation: {
1394
+ type: 'string',
1395
+ required: true
1396
+ }
1397
+ end
1398
+
1399
+ class Cat < Pet
1400
+ expose :huntingSkill, documentation: {
1401
+ type: 'string',
1402
+ description: 'The measured skill for hunting',
1403
+ default: 'lazy',
1404
+ values: %w[
1405
+ clueless
1406
+ lazy
1407
+ adventurous
1408
+ aggressive
1409
+ ]
1410
+ }
1411
+ end
1412
+ end
1413
+ ```
1414
+
1415
+ Should generate this definitions:
1416
+ ```JSON
1417
+ {
1418
+ "definitions": {
1419
+ "Pet": {
1420
+ "type": "object",
1421
+ "discriminator": "petType",
1422
+ "properties": {
1423
+ "name": {
1424
+ "type": "string"
1425
+ },
1426
+ "petType": {
1427
+ "type": "string"
1428
+ }
1429
+ },
1430
+ "required": [
1431
+ "name",
1432
+ "petType"
1433
+ ]
1434
+ },
1435
+ "Cat": {
1436
+ "description": "A representation of a cat",
1437
+ "allOf": [
1438
+ {
1439
+ "$ref": "#/definitions/Pet"
1440
+ },
1441
+ {
1442
+ "type": "object",
1443
+ "properties": {
1444
+ "huntingSkill": {
1445
+ "type": "string",
1446
+ "description": "The measured skill for hunting",
1447
+ "default": "lazy",
1448
+ "enum": [
1449
+ "clueless",
1450
+ "lazy",
1451
+ "adventurous",
1452
+ "aggressive"
1453
+ ]
1454
+ },
1455
+ "petType": {
1456
+ "type": "string",
1457
+ "enum": ["Cat"]
1458
+ }
1459
+ },
1460
+ "required": [
1461
+ "huntingSkill",
1462
+ "petType"
1463
+ ]
1464
+ }
1465
+ ]
1466
+ }
1467
+ }
1468
+ }
1469
+ ```
1470
+
1471
+
1384
1472
 
1385
1473
 
1386
1474
  ## Securing the Swagger UI <a name="oauth"></a>
@@ -1,5 +1,31 @@
1
1
  ## Upgrading Grape-swagger
2
2
 
3
+ ### Upgrading to >= 1.2.0
4
+
5
+ - The entity_name class method is now called on parent classes for inherited entities. Now you can do this
6
+
7
+ ```ruby
8
+ module Some::Long::Module
9
+ class Base < Grape::Entity
10
+ # ... other shared logic
11
+ def self.entity_name
12
+ "V2::#{self.to_s.demodulize}"
13
+ end
14
+ end
15
+
16
+ def MyEntity < Base
17
+ # ....
18
+ end
19
+
20
+ def OtherEntity < Base
21
+ # revert back to the default behavior by hiding the method
22
+ private_class_method :entity_name
23
+ end
24
+ end
25
+ ```
26
+
27
+ - Full class name is modified to use `_` separator (e.g. `A_B_C` instead of `A::B::C`).
28
+
3
29
  ### Upgrading to >= 1.1.0
4
30
 
5
31
  Full class name is used for referencing entity by default (e.g. `A::B::C` instead of just `C`). `Entity` and `Entities` suffixes and prefixes are omitted (e.g. if entity name is `Entities::SomeScope::MyFavourite::Entity` only `SomeScope::MyFavourite` will be used).
@@ -14,7 +14,7 @@ Gem::Specification.new do |s|
14
14
  s.license = 'MIT'
15
15
 
16
16
  s.required_ruby_version = '>= 2.4'
17
- s.add_runtime_dependency 'grape', '~> 1.3.0'
17
+ s.add_runtime_dependency 'grape', '~> 1.3'
18
18
 
19
19
  s.files = `git ls-files`.split("\n")
20
20
  s.test_files = `git ls-files -- {test,spec}/*`.split("\n")
@@ -109,6 +109,7 @@ end
109
109
  module SwaggerDocumentationAdder
110
110
  attr_accessor :combined_namespaces, :combined_namespace_identifiers
111
111
  attr_accessor :combined_routes, :combined_namespace_routes
112
+
112
113
  include SwaggerRouting
113
114
 
114
115
  def add_swagger_documentation(options = {})
@@ -4,8 +4,8 @@ module GrapeSwagger
4
4
  module DocMethods
5
5
  class BuildModelDefinition
6
6
  class << self
7
- def build(model, properties, required)
8
- definition = { type: 'object', properties: properties }
7
+ def build(model, properties, required, other_def_properties = {})
8
+ definition = { type: 'object', properties: properties }.merge(other_def_properties)
9
9
 
10
10
  if required.nil?
11
11
  required_attrs = required_attributes(model)
@@ -17,6 +17,57 @@ module GrapeSwagger
17
17
  definition
18
18
  end
19
19
 
20
+ def parse_params_from_model(parsed_response, model, model_name)
21
+ if parsed_response.is_a?(Hash) && parsed_response.keys.first == :allOf
22
+ refs_or_models = parsed_response[:allOf]
23
+ parsed = parse_refs_and_models(refs_or_models, model)
24
+
25
+ {
26
+ allOf: parsed
27
+ }
28
+ else
29
+ properties, required = parsed_response
30
+ unless properties&.any?
31
+ raise GrapeSwagger::Errors::SwaggerSpec,
32
+ "Empty model #{model_name}, swagger 2.0 doesn't support empty definitions."
33
+ end
34
+ properties, other_def_properties = parse_properties(properties)
35
+
36
+ build(
37
+ model, properties, required, other_def_properties
38
+ )
39
+ end
40
+ end
41
+
42
+ def parse_properties(properties)
43
+ other_properties = {}
44
+
45
+ discriminator_key, discriminator_value =
46
+ properties.find do |_key, value|
47
+ value[:documentation].try(:[], :is_discriminator)
48
+ end
49
+
50
+ if discriminator_key
51
+ discriminator_value.delete(:documentation)
52
+ properties[discriminator_key] = discriminator_value
53
+
54
+ other_properties[:discriminator] = discriminator_key
55
+ end
56
+
57
+ [properties, other_properties]
58
+ end
59
+
60
+ def parse_refs_and_models(refs_or_models, model)
61
+ refs_or_models.map do |ref_or_models|
62
+ if ref_or_models.is_a?(Hash) && ref_or_models.keys.first == '$ref'
63
+ ref_or_models
64
+ else
65
+ properties, required = ref_or_models
66
+ GrapeSwagger::DocMethods::BuildModelDefinition.build(model, properties, required)
67
+ end
68
+ end
69
+ end
70
+
20
71
  private
21
72
 
22
73
  def required_attributes(model)
@@ -48,14 +48,14 @@ module GrapeSwagger
48
48
  end
49
49
 
50
50
  def parse_entity_name(model)
51
- if model.methods(false).include?(:entity_name)
51
+ if model.respond_to?(:entity_name)
52
52
  model.entity_name
53
53
  elsif model.to_s.end_with?('::Entity', '::Entities')
54
- model.to_s.split('::')[0..-2].join('::')
54
+ model.to_s.split('::')[0..-2].join('_')
55
55
  elsif model.to_s.start_with?('Entity::', 'Entities::', 'Representable::')
56
- model.to_s.split('::')[1..-1].join('::')
56
+ model.to_s.split('::')[1..-1].join('_')
57
57
  else
58
- model.to_s
58
+ model.to_s.split('::').join('_')
59
59
  end
60
60
  end
61
61
 
@@ -16,8 +16,8 @@ module GrapeSwagger
16
16
 
17
17
  def manipulate(path)
18
18
  operation = path.split('/').map(&:capitalize).join
19
- operation.gsub!(/\-(\w)/, &:upcase).delete!('-') if operation[/\-(\w)/]
20
- operation.gsub!(/\_(\w)/, &:upcase).delete!('_') if operation.include?('_')
19
+ operation.gsub!(/-(\w)/, &:upcase).delete!('-') if operation[/-(\w)/]
20
+ operation.gsub!(/_(\w)/, &:upcase).delete!('_') if operation.include?('_')
21
21
  operation.gsub!(/\.(\w)/, &:upcase).delete!('.') if operation[/\.(\w)/]
22
22
  if path.include?('{')
23
23
  operation.gsub!(/\{(\w)/, &:upcase)
@@ -77,6 +77,19 @@ module GrapeSwagger
77
77
 
78
78
  param_type ||= value_type[:param_type]
79
79
 
80
+ array_items = parse_array_item(
81
+ definitions,
82
+ type,
83
+ value_type
84
+ )
85
+
86
+ @parsed_param[:in] = param_type || 'formData'
87
+ @parsed_param[:items] = array_items
88
+ @parsed_param[:type] = 'array'
89
+ @parsed_param[:collectionFormat] = collection_format if DataType.collections.include?(collection_format)
90
+ end
91
+
92
+ def parse_array_item(definitions, type, value_type)
80
93
  array_items = {}
81
94
  if definitions[value_type[:data_type]]
82
95
  array_items['$ref'] = "#/definitions/#{@parsed_param[:type]}"
@@ -91,10 +104,7 @@ module GrapeSwagger
91
104
 
92
105
  array_items[:default] = value_type[:default] if value_type[:default].present?
93
106
 
94
- @parsed_param[:in] = param_type || 'formData'
95
- @parsed_param[:items] = array_items
96
- @parsed_param[:type] = 'array'
97
- @parsed_param[:collectionFormat] = collection_format if DataType.collections.include?(collection_format)
107
+ array_items
98
108
  end
99
109
 
100
110
  def document_additional_properties(settings)
@@ -196,10 +196,7 @@ module Grape
196
196
  end
197
197
 
198
198
  def response_object(route, options)
199
- codes = http_codes_from_route(route)
200
- codes.map! { |x| x.is_a?(Array) ? { code: x[0], message: x[1], model: x[2], examples: x[3], headers: x[4] } : x }
201
-
202
- codes.each_with_object({}) do |value, memo|
199
+ codes(route).each_with_object({}) do |value, memo|
203
200
  value[:message] ||= ''
204
201
  memo[value[:code]] = { description: value[:message] }
205
202
 
@@ -225,6 +222,12 @@ module Grape
225
222
  end
226
223
  end
227
224
 
225
+ def codes(route)
226
+ http_codes_from_route(route).map do |x|
227
+ x.is_a?(Array) ? { code: x[0], message: x[1], model: x[2], examples: x[3], headers: x[4] } : x
228
+ end
229
+ end
230
+
228
231
  def success_code?(code)
229
232
  status = code.is_a?(Array) ? code.first : code[:code]
230
233
  status.between?(200, 299)
@@ -340,12 +343,10 @@ module Grape
340
343
  parser = GrapeSwagger.model_parsers.find(model)
341
344
  raise GrapeSwagger::Errors::UnregisteredParser, "No parser registered for #{model_name}." unless parser
342
345
 
343
- properties, required = parser.new(model, self).call
344
- unless properties&.any?
345
- raise GrapeSwagger::Errors::SwaggerSpec,
346
- "Empty model #{model_name}, swagger 2.0 doesn't support empty definitions."
347
- end
348
- @definitions[model_name] = GrapeSwagger::DocMethods::BuildModelDefinition.build(model, properties, required)
346
+ parsed_response = parser.new(model, self).call
347
+
348
+ @definitions[model_name] =
349
+ GrapeSwagger::DocMethods::BuildModelDefinition.parse_params_from_model(parsed_response, model, model_name)
349
350
 
350
351
  model_name
351
352
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GrapeSwagger
4
- VERSION = '1.1.0'
4
+ VERSION = '1.2.0'
5
5
  end
@@ -35,5 +35,5 @@ describe '#427 nested entity given as string' do
35
35
  JSON.parse(last_response.body)['definitions']
36
36
  end
37
37
 
38
- specify { expect(subject.keys).to include 'RoleEntity', 'Permission::WithoutRole' }
38
+ specify { expect(subject.keys).to include 'RoleEntity', 'Permission_WithoutRole' }
39
39
  end
@@ -55,6 +55,8 @@ describe 'definition names' do
55
55
  class Class7
56
56
  class SeventhEntity < Class6::SixthEntity
57
57
  expose :seventh_thing
58
+
59
+ private_class_method :entity_name
58
60
  end
59
61
  end
60
62
  end
@@ -82,11 +84,11 @@ describe 'definition names' do
82
84
  JSON.parse(last_response.body)['definitions']
83
85
  end
84
86
 
85
- specify { expect(subject).to include 'TestDefinition::DummyEntities::WithVeryLongName::AnotherGroupingModule::Class1' }
86
- specify { expect(subject).to include 'TestDefinition::DummyEntities::WithVeryLongName::AnotherGroupingModule::Class2' }
87
+ specify { expect(subject).to include 'TestDefinition_DummyEntities_WithVeryLongName_AnotherGroupingModule_Class1' }
88
+ specify { expect(subject).to include 'TestDefinition_DummyEntities_WithVeryLongName_AnotherGroupingModule_Class2' }
87
89
  specify { expect(subject).to include 'FooKlass' }
88
- specify { expect(subject).to include 'TestDefinition::DummyEntities::WithVeryLongName::AnotherGroupingModule::Class4::FourthEntity' }
89
- specify { expect(subject).to include 'TestDefinition::DummyEntities::WithVeryLongName::AnotherGroupingModule::Class5::FithEntity' }
90
+ specify { expect(subject).to include 'TestDefinition_DummyEntities_WithVeryLongName_AnotherGroupingModule_Class4_FourthEntity' }
91
+ specify { expect(subject).to include 'TestDefinition_DummyEntities_WithVeryLongName_AnotherGroupingModule_Class5_FithEntity' }
90
92
  specify { expect(subject).to include 'BarKlass' }
91
- specify { expect(subject).to include 'TestDefinition::DummyEntities::WithVeryLongName::AnotherGroupingModule::Class7::SeventhEntity' }
93
+ specify { expect(subject).to include 'TestDefinition_DummyEntities_WithVeryLongName_AnotherGroupingModule_Class7_SeventhEntity' }
92
94
  end
@@ -49,6 +49,18 @@ describe GrapeSwagger::DocMethods::DataType do
49
49
  it { is_expected.to eq 'MyInteger' }
50
50
  end
51
51
 
52
+ describe 'Types in array with inherited entity_name' do
53
+ before do
54
+ stub_const 'EntityBase', Class.new
55
+ allow(EntityBase).to receive(:entity_name).and_return 'MyInteger'
56
+ stub_const 'MyEntity', Class.new(EntityBase)
57
+ end
58
+
59
+ let(:value) { { type: '[MyEntity]' } }
60
+
61
+ it { is_expected.to eq 'MyInteger' }
62
+ end
63
+
52
64
  describe 'Rack::Multipart::UploadedFile' do
53
65
  let(:value) { { type: Rack::Multipart::UploadedFile } }
54
66
 
@@ -189,7 +189,7 @@ describe 'setting of param type, such as `query`, `path`, `formData`, `body`, `h
189
189
  'type' => 'object',
190
190
  'properties' => {
191
191
  'data' => {
192
- '$ref' => '#/definitions/NestedModule::ApiResponse',
192
+ '$ref' => '#/definitions/NestedModule_ApiResponse',
193
193
  'description' => 'request data'
194
194
  }
195
195
  },
@@ -207,7 +207,7 @@ describe 'setting of param type, such as `query`, `path`, `formData`, `body`, `h
207
207
  end
208
208
 
209
209
  specify do
210
- expect(subject['definitions']['NestedModule::ApiResponse']).not_to be_nil
210
+ expect(subject['definitions']['NestedModule_ApiResponse']).not_to be_nil
211
211
  end
212
212
 
213
213
  specify do
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'Inheritance and Discriminator' do
6
+ before :all do
7
+ module InheritanceTest
8
+ module Entities
9
+ # example from https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#models-with-polymorphism-supports
10
+ class Pet < Grape::Entity
11
+ expose :type, documentation: {
12
+ type: 'string',
13
+ is_discriminator: true,
14
+ required: true
15
+ }
16
+ expose :name, documentation: {
17
+ type: 'string',
18
+ required: true
19
+ }
20
+ end
21
+
22
+ class Cat < Pet
23
+ expose :huntingSkill, documentation: {
24
+ type: 'string',
25
+ description: 'The measured skill for hunting',
26
+ default: 'lazy',
27
+ values: %w[
28
+ clueless
29
+ lazy
30
+ adventurous
31
+ aggressive
32
+ ]
33
+ }
34
+ end
35
+ end
36
+ class NameApi < Grape::API
37
+ add_swagger_documentation models: [Entities::Pet, Entities::Cat]
38
+ end
39
+ end
40
+ end
41
+
42
+ context 'Parent model' do
43
+ let(:app) { InheritanceTest::NameApi }
44
+
45
+ subject do
46
+ get '/swagger_doc'
47
+ JSON.parse(last_response.body)['definitions']
48
+ end
49
+
50
+ specify do
51
+ subject['InheritanceTest_Entities_Pet'].key?('discriminator')
52
+ subject['InheritanceTest_Entities_Pet']['discriminator'] = 'type'
53
+ subject['InheritanceTest_Entities_Cat'].key?('allOf')
54
+ end
55
+ end
56
+ end
@@ -22,6 +22,20 @@ describe 'referenceEntity' do
22
22
  expose :title, documentation: { type: 'string', desc: 'Title of the kind.' }
23
23
  expose :something, documentation: { type: Something, desc: 'Something interesting.' }
24
24
  end
25
+
26
+ class Base < Grape::Entity
27
+ def self.entity_name
28
+ parts = to_s.split('::')
29
+
30
+ "MyAPI::#{parts.last}"
31
+ end
32
+
33
+ expose :title, documentation: { type: 'string', desc: 'Title of the parent.' }
34
+ end
35
+
36
+ class Child < Base
37
+ expose :child, documentation: { type: 'string', desc: 'Child property.' }
38
+ end
25
39
  end
26
40
 
27
41
  class ResponseModelApi < Grape::API
@@ -40,6 +54,16 @@ describe 'referenceEntity' do
40
54
  present kind, with: Entities::Kind
41
55
  end
42
56
 
57
+ desc 'This returns a child entity',
58
+ entity: Entities::Child,
59
+ http_codes: [
60
+ { code: 200, message: 'OK', model: Entities::Child }
61
+ ]
62
+ get '/child' do
63
+ child = OpenStruct.new text: 'child'
64
+ present child, with: Entities::Child
65
+ end
66
+
43
67
  add_swagger_documentation # models: [MyAPI::Entities::Something, MyAPI::Entities::Kind]
44
68
  end
45
69
  end
@@ -49,36 +73,57 @@ describe 'referenceEntity' do
49
73
  MyAPI::ResponseModelApi
50
74
  end
51
75
 
52
- subject do
53
- get '/swagger_doc/kind'
54
- JSON.parse(last_response.body)
76
+ describe 'kind' do
77
+ subject do
78
+ get '/swagger_doc/kind'
79
+ JSON.parse(last_response.body)
80
+ end
81
+
82
+ it 'should document specified models' do
83
+ expect(subject['paths']['/kind']['get']['parameters']).to eq [{
84
+ 'in' => 'query',
85
+ 'name' => 'something',
86
+ 'description' => 'Something interesting.',
87
+ 'type' => 'SomethingCustom',
88
+ 'required' => false
89
+ }]
90
+
91
+ expect(subject['definitions'].keys).to include 'SomethingCustom'
92
+ expect(subject['definitions']['SomethingCustom']).to eq(
93
+ 'type' => 'object', 'properties' => { 'text' => { 'type' => 'string', 'description' => 'Content of something.' } }
94
+ )
95
+
96
+ expect(subject['definitions'].keys).to include 'KindCustom'
97
+ expect(subject['definitions']['KindCustom']).to eq(
98
+ 'type' => 'object',
99
+ 'properties' => {
100
+ 'title' => { 'type' => 'string', 'description' => 'Title of the kind.' },
101
+ 'something' => {
102
+ '$ref' => '#/definitions/SomethingCustom',
103
+ 'description' => 'Something interesting.'
104
+ }
105
+ },
106
+ 'description' => 'This returns kind and something or an error'
107
+ )
108
+ end
55
109
  end
56
110
 
57
- it 'should document specified models' do
58
- expect(subject['paths']['/kind']['get']['parameters']).to eq [{
59
- 'in' => 'query',
60
- 'name' => 'something',
61
- 'description' => 'Something interesting.',
62
- 'type' => 'SomethingCustom',
63
- 'required' => false
64
- }]
65
-
66
- expect(subject['definitions'].keys).to include 'SomethingCustom'
67
- expect(subject['definitions']['SomethingCustom']).to eq(
68
- 'type' => 'object', 'properties' => { 'text' => { 'type' => 'string', 'description' => 'Content of something.' } }
69
- )
70
-
71
- expect(subject['definitions'].keys).to include 'KindCustom'
72
- expect(subject['definitions']['KindCustom']).to eq(
73
- 'type' => 'object',
74
- 'properties' => {
75
- 'title' => { 'type' => 'string', 'description' => 'Title of the kind.' },
76
- 'something' => {
77
- '$ref' => '#/definitions/SomethingCustom',
78
- 'description' => 'Something interesting.'
79
- }
80
- },
81
- 'description' => 'This returns kind and something or an error'
82
- )
111
+ describe 'child' do
112
+ subject do
113
+ get '/swagger_doc/child'
114
+ JSON.parse(last_response.body)
115
+ end
116
+
117
+ it 'should document specified models' do
118
+ expect(subject['definitions'].keys).to include 'MyAPI::Child'
119
+ expect(subject['definitions']['MyAPI::Child']).to eq(
120
+ 'type' => 'object',
121
+ 'properties' => {
122
+ 'title' => { 'type' => 'string', 'description' => 'Title of the parent.' },
123
+ 'child' => { 'type' => 'string', 'description' => 'Child property.' }
124
+ },
125
+ 'description' => 'This returns a child entity'
126
+ )
127
+ end
83
128
  end
84
129
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape-swagger
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Vandecasteele
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-20 00:00:00.000000000 Z
11
+ date: 2020-07-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: grape
@@ -16,15 +16,15 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.3.0
19
+ version: '1.3'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 1.3.0
27
- description:
26
+ version: '1.3'
27
+ description:
28
28
  email:
29
29
  - tim.vandecasteele@gmail.com
30
30
  executables: []
@@ -156,6 +156,7 @@ files:
156
156
  - spec/swagger_v2/guarded_endpoint_spec.rb
157
157
  - spec/swagger_v2/hide_api_spec.rb
158
158
  - spec/swagger_v2/host_spec.rb
159
+ - spec/swagger_v2/inheritance_and_discriminator_spec.rb
159
160
  - spec/swagger_v2/mount_override_api_spec.rb
160
161
  - spec/swagger_v2/mounted_target_class_spec.rb
161
162
  - spec/swagger_v2/namespace_tags_prefix_spec.rb
@@ -179,7 +180,7 @@ homepage: https://github.com/ruby-grape/grape-swagger
179
180
  licenses:
180
181
  - MIT
181
182
  metadata: {}
182
- post_install_message:
183
+ post_install_message:
183
184
  rdoc_options: []
184
185
  require_paths:
185
186
  - lib
@@ -195,7 +196,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
195
196
  version: '0'
196
197
  requirements: []
197
198
  rubygems_version: 3.1.2
198
- signing_key:
199
+ signing_key:
199
200
  specification_version: 4
200
201
  summary: Add auto generated documentation to your Grape API that can be displayed
201
202
  with Swagger.
@@ -279,6 +280,7 @@ test_files:
279
280
  - spec/swagger_v2/guarded_endpoint_spec.rb
280
281
  - spec/swagger_v2/hide_api_spec.rb
281
282
  - spec/swagger_v2/host_spec.rb
283
+ - spec/swagger_v2/inheritance_and_discriminator_spec.rb
282
284
  - spec/swagger_v2/mount_override_api_spec.rb
283
285
  - spec/swagger_v2/mounted_target_class_spec.rb
284
286
  - spec/swagger_v2/namespace_tags_prefix_spec.rb