swaggard 4.0.3 → 4.1.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 +4 -4
- data/README.md +2 -2
- data/lib/swaggard/parsers/property.rb +2 -1
- data/lib/swaggard/swagger/definition.rb +23 -10
- data/lib/swaggard/swagger/parameters/body.rb +4 -1
- data/lib/swaggard/swagger/property.rb +7 -1
- data/lib/swaggard/version.rb +1 -1
- data/spec/swaggard/parsers/property_spec.rb +40 -0
- data/spec/swaggard/swagger/definition_spec.rb +49 -0
- data/spec/swaggard/swagger/parameters/body_spec.rb +51 -0
- data/spec/swaggard/swagger/property_spec.rb +33 -0
- metadata +9 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 28d2106f9e0d61087b74c97d99c4e3e6c848b9bee4afa7fb6a828db0466cb134
|
|
4
|
+
data.tar.gz: 668252d84bbdc87a23ed4191cc5baae2c2c7dfbe2b06cb794d8a7fe947cbf70c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fbc1a171bbb0b3eaf2d285e4eebb9e3b2d76196745865afb727de157be519be9604d12af0745c9d2a7d73a5b52f0916230e98372bbc94af67159552cf72302dc
|
|
7
|
+
data.tar.gz: a648d45fc2cffc78502e548ccafcfbc2ff4ece0bccee7a75b3d4827cffab98d1672304bca5d63bcd1b94f1f0dc4d7a8cd373faea5adf61ca356f4f553928493c
|
data/README.md
CHANGED
|
@@ -139,7 +139,7 @@ Add YARD comments to provide richer documentation:
|
|
|
139
139
|
|
|
140
140
|
- `@tag name` — Group this controller under `name`. Defaults to the controller path if `ignore_untagged_controllers` is false.
|
|
141
141
|
- `@query_parameter [type] name` — Query string parameter.
|
|
142
|
-
- `@body_parameter [type] name` — Request body property. Generates a `requestBody` in the OpenAPI output.
|
|
142
|
+
- `@body_parameter [type] name` — Request body property. Generates a `requestBody` in the OpenAPI output. Use `[type]!` to mark the property as required and `name(deprecated)` to mark it as deprecated.
|
|
143
143
|
- `@form_parameter [type] name` — Form data parameter (`application/x-www-form-urlencoded`).
|
|
144
144
|
- `@parameter_list` — Enum-style query parameter list.
|
|
145
145
|
- `@response_class type` — Response schema type. Supports `Array<Type>` for array responses.
|
|
@@ -162,7 +162,7 @@ To document all controllers including those without a `@tag`:
|
|
|
162
162
|
|
|
163
163
|
### Models
|
|
164
164
|
|
|
165
|
-
- `@attr [type] name` — Model attribute.
|
|
165
|
+
- `@attr [type] name` — Model attribute. Use `!name` to mark the attribute as required and `name(deprecated)` to mark it as deprecated.
|
|
166
166
|
- `@ignore_inherited` — Do not inherit properties from parent class.
|
|
167
167
|
|
|
168
168
|
|
|
@@ -11,10 +11,11 @@ module Swaggard
|
|
|
11
11
|
options, description = options_and_description.match(/\A(\[.*\])?(.*)\Z/).captures
|
|
12
12
|
options = options ? options.gsub(/\[?\]?\s?/, '').split(',') : []
|
|
13
13
|
description = description.strip
|
|
14
|
+
deprecated = name.gsub!(/\(deprecated\)\z/, '')
|
|
14
15
|
required = name.gsub!(/^!/, '')
|
|
15
16
|
type = Parsers::Type.run(yard_object.types.first)
|
|
16
17
|
|
|
17
|
-
Swaggard::Swagger::Property.new(name, type, description, required.present?, options)
|
|
18
|
+
Swaggard::Swagger::Property.new(name, type, description, required.present?, options, deprecated.present?)
|
|
18
19
|
end
|
|
19
20
|
end
|
|
20
21
|
end
|
|
@@ -5,13 +5,14 @@ module Swaggard
|
|
|
5
5
|
attr_reader :id
|
|
6
6
|
attr_writer :description, :title, :ignore_inherited
|
|
7
7
|
|
|
8
|
-
def initialize(id, ancestors: [])
|
|
8
|
+
def initialize(id, ancestors: [], collection: false)
|
|
9
9
|
@id = id
|
|
10
10
|
@title = ''
|
|
11
11
|
@properties = []
|
|
12
12
|
@description = ''
|
|
13
13
|
@ancestors = ancestors
|
|
14
14
|
@ignore_inherited = false
|
|
15
|
+
@collection = collection
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
def add_property(property)
|
|
@@ -41,19 +42,31 @@ module Swaggard
|
|
|
41
42
|
end
|
|
42
43
|
|
|
43
44
|
def to_doc(definitions)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
all_properties = properties(definitions)
|
|
46
|
+
properties_hash = Hash[all_properties.map { |property| [property.id, property.to_doc] }]
|
|
47
|
+
required_properties = all_properties.select(&:required?).map(&:id)
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
if @collection
|
|
50
|
+
items = { 'type' => 'object', 'properties' => properties_hash }
|
|
51
|
+
items['required'] = required_properties if required_properties.any?
|
|
49
52
|
|
|
50
|
-
|
|
53
|
+
{}.tap do |doc|
|
|
54
|
+
doc['title'] = @title if @title.present?
|
|
55
|
+
doc['type'] = 'array'
|
|
56
|
+
doc['description'] = @description if @description.present?
|
|
57
|
+
doc['items'] = items
|
|
58
|
+
end
|
|
59
|
+
else
|
|
60
|
+
{}.tap do |doc|
|
|
61
|
+
doc['title'] = @title if @title.present?
|
|
62
|
+
doc['type'] = 'object'
|
|
51
63
|
|
|
52
|
-
|
|
53
|
-
required_properties = all_properties.select(&:required?).map(&:id)
|
|
54
|
-
doc['required'] = required_properties if required_properties.any?
|
|
55
|
-
end
|
|
64
|
+
doc['description'] = @description if @description.present?
|
|
56
65
|
|
|
66
|
+
doc['properties'] = properties_hash
|
|
67
|
+
doc['required'] = required_properties if required_properties.any?
|
|
68
|
+
end
|
|
69
|
+
end
|
|
57
70
|
end
|
|
58
71
|
|
|
59
72
|
end
|
|
@@ -72,15 +72,17 @@ module Swaggard
|
|
|
72
72
|
elsif @options.present?
|
|
73
73
|
result['enum'] = @options
|
|
74
74
|
end
|
|
75
|
+
result['deprecated'] = true if @deprecated
|
|
75
76
|
result
|
|
76
77
|
end
|
|
77
78
|
|
|
78
79
|
# Example: [Array] status Filter by status. (e.g. status[]=1&status[]=2&status[]=3)
|
|
79
80
|
# Example: [Array] status(required) Filter by status. (e.g. status[]=1&status[]=2&status[]=3)
|
|
80
81
|
# Example: [Integer] media[media_type_id] ID of the desired media type.
|
|
82
|
+
# Example: [Boolean] uses_tobacco(deprecated) Whether the patient uses tobacco.
|
|
81
83
|
def parse(string)
|
|
82
84
|
string.gsub!("\n", ' ')
|
|
83
|
-
data_type, required, name, options_and_description = string.match(/\A\[(\S*)\](!)?\s*([\w\[\]]*)\s*(.*)\Z/).captures
|
|
85
|
+
data_type, required, name, deprecated, options_and_description = string.match(/\A\[(\S*)\](!)?\s*([\w\[\]]*)(\(deprecated\))?\s*(.*)\Z/).captures
|
|
84
86
|
options, description = options_and_description.match(/\A(\[.*\])?(.*)\Z/).captures
|
|
85
87
|
options = options ? options.gsub(/\[?\]?\s?/, '').split(',') : []
|
|
86
88
|
|
|
@@ -89,6 +91,7 @@ module Swaggard
|
|
|
89
91
|
@type = Parsers::Type.run(data_type)
|
|
90
92
|
@required = required
|
|
91
93
|
@options = options
|
|
94
|
+
@deprecated = deprecated.present?
|
|
92
95
|
end
|
|
93
96
|
end
|
|
94
97
|
end
|
|
@@ -5,22 +5,28 @@ module Swaggard
|
|
|
5
5
|
class Property
|
|
6
6
|
attr_reader :id, :type, :description
|
|
7
7
|
|
|
8
|
-
def initialize(name, type, description = '', required = false, options = [])
|
|
8
|
+
def initialize(name, type, description = '', required = false, options = [], deprecated = false)
|
|
9
9
|
@id = name
|
|
10
10
|
@type = type
|
|
11
11
|
@description = description
|
|
12
12
|
@required = required
|
|
13
13
|
@options = options
|
|
14
|
+
@deprecated = deprecated
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
def required?
|
|
17
18
|
@required
|
|
18
19
|
end
|
|
19
20
|
|
|
21
|
+
def deprecated?
|
|
22
|
+
@deprecated
|
|
23
|
+
end
|
|
24
|
+
|
|
20
25
|
def to_doc
|
|
21
26
|
result = @type.to_doc
|
|
22
27
|
result['description'] = @description if @description.present?
|
|
23
28
|
result['enum'] = @options if @options.present?
|
|
29
|
+
result['deprecated'] = true if @deprecated
|
|
24
30
|
result
|
|
25
31
|
end
|
|
26
32
|
end
|
data/lib/swaggard/version.rb
CHANGED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Swaggard::Parsers::Property do
|
|
4
|
+
def yard_tag(name, text: 'A description', types: ['string'])
|
|
5
|
+
YARD::Tags::Tag.new('attr', text, types, name)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
describe '.run' do
|
|
9
|
+
it 'parses a plain attribute' do
|
|
10
|
+
property = described_class.run(yard_tag('name'))
|
|
11
|
+
|
|
12
|
+
expect(property.id).to eq('name')
|
|
13
|
+
expect(property).not_to be_required
|
|
14
|
+
expect(property).not_to be_deprecated
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'parses the required marker' do
|
|
18
|
+
property = described_class.run(yard_tag('!name'))
|
|
19
|
+
|
|
20
|
+
expect(property.id).to eq('name')
|
|
21
|
+
expect(property).to be_required
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it 'parses the deprecated marker' do
|
|
25
|
+
property = described_class.run(yard_tag('uses_tobacco(deprecated)', types: ['boolean']))
|
|
26
|
+
|
|
27
|
+
expect(property.id).to eq('uses_tobacco')
|
|
28
|
+
expect(property).to be_deprecated
|
|
29
|
+
expect(property.to_doc).to include('deprecated' => true)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'combines the required and deprecated markers' do
|
|
33
|
+
property = described_class.run(yard_tag('!name(deprecated)'))
|
|
34
|
+
|
|
35
|
+
expect(property.id).to eq('name')
|
|
36
|
+
expect(property).to be_required
|
|
37
|
+
expect(property).to be_deprecated
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Swaggard::Swagger::Definition do
|
|
4
|
+
let(:property) { Swaggard::Swagger::Property.new('name', Swaggard::Swagger::Type.new(:string)) }
|
|
5
|
+
|
|
6
|
+
describe '#to_doc' do
|
|
7
|
+
context 'when collection is false (default)' do
|
|
8
|
+
subject(:definition) { described_class.new('Foo') }
|
|
9
|
+
|
|
10
|
+
before { definition.add_property(property) }
|
|
11
|
+
|
|
12
|
+
it 'emits a type: object schema with inline properties' do
|
|
13
|
+
expect(definition.to_doc({})).to eq(
|
|
14
|
+
'type' => 'object',
|
|
15
|
+
'properties' => { 'name' => { 'type' => 'string' } }
|
|
16
|
+
)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context 'when collection is true' do
|
|
21
|
+
subject(:definition) { described_class.new('Foo_all', collection: true) }
|
|
22
|
+
|
|
23
|
+
before { definition.add_property(property) }
|
|
24
|
+
|
|
25
|
+
it 'emits a type: array schema with properties wrapped under items' do
|
|
26
|
+
expect(definition.to_doc({})).to eq(
|
|
27
|
+
'type' => 'array',
|
|
28
|
+
'items' => {
|
|
29
|
+
'type' => 'object',
|
|
30
|
+
'properties' => { 'name' => { 'type' => 'string' } }
|
|
31
|
+
}
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context 'with required properties' do
|
|
36
|
+
let(:property) do
|
|
37
|
+
Swaggard::Swagger::Property.new('name', Swaggard::Swagger::Type.new(:string), '', true)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'places the required array inside items' do
|
|
41
|
+
doc = definition.to_doc({})
|
|
42
|
+
|
|
43
|
+
expect(doc['required']).to be_nil
|
|
44
|
+
expect(doc['items']['required']).to eq(['name'])
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Swaggard::Swagger::Parameters::Body do
|
|
4
|
+
subject(:body) { described_class.new('PetsController.create') }
|
|
5
|
+
|
|
6
|
+
def property_doc(name)
|
|
7
|
+
body.definition.to_doc({})['properties'][name]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
describe '#add_property' do
|
|
11
|
+
it 'parses type, name and description' do
|
|
12
|
+
body.add_property('[String] name The name of the pet')
|
|
13
|
+
|
|
14
|
+
expect(property_doc('name')).to eq('type' => 'string', 'description' => 'The name of the pet')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'parses the required marker' do
|
|
18
|
+
body.add_property('[String]! name The name of the pet')
|
|
19
|
+
|
|
20
|
+
expect(body.definition.to_doc({})['required']).to eq(['name'])
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'parses the deprecated marker' do
|
|
24
|
+
body.add_property('[Boolean] uses_tobacco(deprecated) Use lifestyle instead.')
|
|
25
|
+
|
|
26
|
+
expect(property_doc('uses_tobacco')).to eq(
|
|
27
|
+
'type' => 'boolean',
|
|
28
|
+
'description' => 'Use lifestyle instead.',
|
|
29
|
+
'deprecated' => true
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'combines the required and deprecated markers' do
|
|
34
|
+
body.add_property('[String]! name(deprecated) The name of the pet')
|
|
35
|
+
|
|
36
|
+
expect(property_doc('name')['deprecated']).to be(true)
|
|
37
|
+
expect(body.definition.to_doc({})['required']).to eq(['name'])
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'keeps enum options working alongside the deprecated marker' do
|
|
41
|
+
body.add_property('[String] status(deprecated) [active,inactive] The status')
|
|
42
|
+
|
|
43
|
+
expect(property_doc('status')).to eq(
|
|
44
|
+
'type' => 'string',
|
|
45
|
+
'description' => ' The status',
|
|
46
|
+
'enum' => %w[active inactive],
|
|
47
|
+
'deprecated' => true
|
|
48
|
+
)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Swaggard::Swagger::Property do
|
|
4
|
+
describe '#to_doc' do
|
|
5
|
+
let(:type) { Swaggard::Swagger::Type.new(:string) }
|
|
6
|
+
|
|
7
|
+
it 'emits the type only by default' do
|
|
8
|
+
property = described_class.new('name', type)
|
|
9
|
+
|
|
10
|
+
expect(property.to_doc).to eq('type' => 'string')
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'emits the description when present' do
|
|
14
|
+
property = described_class.new('name', type, 'The full name')
|
|
15
|
+
|
|
16
|
+
expect(property.to_doc).to eq('type' => 'string', 'description' => 'The full name')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'emits deprecated when the property is deprecated' do
|
|
20
|
+
property = described_class.new('name', type, '', false, [], true)
|
|
21
|
+
|
|
22
|
+
expect(property.to_doc).to eq('type' => 'string', 'deprecated' => true)
|
|
23
|
+
expect(property).to be_deprecated
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'does not emit deprecated when the property is not deprecated' do
|
|
27
|
+
property = described_class.new('name', type)
|
|
28
|
+
|
|
29
|
+
expect(property.to_doc).not_to have_key('deprecated')
|
|
30
|
+
expect(property).not_to be_deprecated
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: swaggard
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.0
|
|
4
|
+
version: 4.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Adrian Gomez
|
|
@@ -162,6 +162,10 @@ files:
|
|
|
162
162
|
- spec/integration/openapi_spec.rb
|
|
163
163
|
- spec/integration/swaggard_spec.rb
|
|
164
164
|
- spec/spec_helper.rb
|
|
165
|
+
- spec/swaggard/parsers/property_spec.rb
|
|
166
|
+
- spec/swaggard/swagger/definition_spec.rb
|
|
167
|
+
- spec/swaggard/swagger/parameters/body_spec.rb
|
|
168
|
+
- spec/swaggard/swagger/property_spec.rb
|
|
165
169
|
homepage: https://github.com/adrian-gomez/swaggard
|
|
166
170
|
licenses:
|
|
167
171
|
- MIT
|
|
@@ -199,3 +203,7 @@ test_files:
|
|
|
199
203
|
- spec/integration/openapi_spec.rb
|
|
200
204
|
- spec/integration/swaggard_spec.rb
|
|
201
205
|
- spec/spec_helper.rb
|
|
206
|
+
- spec/swaggard/parsers/property_spec.rb
|
|
207
|
+
- spec/swaggard/swagger/definition_spec.rb
|
|
208
|
+
- spec/swaggard/swagger/parameters/body_spec.rb
|
|
209
|
+
- spec/swaggard/swagger/property_spec.rb
|