swaggard 1.0.1 → 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 +4 -4
- data/README.md +9 -0
- data/config/initializers/assets.rb +8 -5
- data/lib/swaggard/api_definition.rb +3 -3
- data/lib/swaggard/engine.rb +13 -10
- data/lib/swaggard/parsers/controller.rb +11 -5
- data/lib/swaggard/parsers/models.rb +19 -10
- data/lib/swaggard/swagger/definition.rb +27 -5
- data/lib/swaggard/swagger/operation.rb +7 -3
- data/lib/swaggard/swagger/tag.rb +5 -6
- data/lib/swaggard/version.rb +1 -1
- data/lib/swaggard.rb +23 -16
- metadata +16 -18
- data/spec/fixtures/dummy/log/development.log +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a49ea847a04d150e7b42923bf6a8290950f5fa18c53deba16907c36a59a664f
|
4
|
+
data.tar.gz: 3986acba75f1b962c13ca5b93ceb2f1481609f3516b5438689822d0916675952
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3fd5f67a5c03861c8e78a77088f1aa4712a75d9fb251a2c1acb2e597f5609ae81b935d5ac090f5e49ae9dba7ab0a0ceb17be40a553ea183185d3fc88cf14c13f
|
7
|
+
data.tar.gz: db5042eb41674f3f85f94aa860743eed9861eb49d0bc44b9ed02bc36dcb578816552ff44dc2016a61bb01c5f90d71c0b3a31b23f55fd538d8b53403a9ac3cc85
|
data/README.md
CHANGED
@@ -11,6 +11,8 @@ the supported rails version.
|
|
11
11
|
|
12
12
|
Swaggard Version | Swagger UI Version | Supported Rails Versions
|
13
13
|
---------------- | ------------------- | ------------------------
|
14
|
+
1.1.x | 2.2.8 | 4 - 6
|
15
|
+
1.0.x | 2.2.8 | 4 - 5
|
14
16
|
0.5.x | 2.2.8 | 4 - 5
|
15
17
|
0.4.x | 2.2.8 | 4
|
16
18
|
0.3.x | 2.1.3 | 4
|
@@ -43,6 +45,13 @@ Mount your engine
|
|
43
45
|
|
44
46
|
mount Swaggard::Engine, at: '/api_docs/swagger/'
|
45
47
|
|
48
|
+
Make sure the asset pipeline is enabled by either requiring all railties
|
49
|
+
or just the sprockets one:
|
50
|
+
|
51
|
+
# config/application.rb
|
52
|
+
|
53
|
+
require 'sprockets/railtie'
|
54
|
+
|
46
55
|
Access your service documentation
|
47
56
|
|
48
57
|
open http://localhost:3000/api_docs/swagger/
|
@@ -1,5 +1,8 @@
|
|
1
|
-
Rails.
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
if Rails::Application.instance_methods.include?(:assets_manifest)
|
2
|
+
Rails.application.config.assets.precompile += %w[swaggard/application_print.css
|
3
|
+
swaggard/favicon-32x32.png
|
4
|
+
swaggard/favicon-16x16.png
|
5
|
+
swaggard/lang/*.js
|
6
|
+
swaggard/logo_small.png]
|
7
|
+
|
8
|
+
end
|
@@ -7,7 +7,7 @@ module Swaggard
|
|
7
7
|
def initialize
|
8
8
|
@paths = {}
|
9
9
|
@tags = {}
|
10
|
-
@definitions =
|
10
|
+
@definitions = {}
|
11
11
|
end
|
12
12
|
|
13
13
|
def add_tag(tag)
|
@@ -19,7 +19,7 @@ module Swaggard
|
|
19
19
|
def add_operation(operation)
|
20
20
|
@paths[operation.path] ||= Swagger::Path.new(operation.path)
|
21
21
|
@paths[operation.path].add_operation(operation)
|
22
|
-
@definitions.
|
22
|
+
@definitions.merge!(operation.definitions)
|
23
23
|
end
|
24
24
|
|
25
25
|
def ignore_put_if_patch!
|
@@ -51,7 +51,7 @@ module Swaggard
|
|
51
51
|
'produces' => Swaggard.configuration.api_formats.map { |format| "application/#{format}" },
|
52
52
|
'tags' => @tags.map { |_, tag| tag.to_doc },
|
53
53
|
'paths' => Hash[@paths.values.map { |path| [format_path(path.path), path.to_doc] }],
|
54
|
-
'definitions' => Hash[@definitions.map { |definition| [
|
54
|
+
'definitions' => Hash[@definitions.map { |id, definition| [id, definition.to_doc(@definitions)] }]
|
55
55
|
}
|
56
56
|
end
|
57
57
|
|
data/lib/swaggard/engine.rb
CHANGED
@@ -1,20 +1,23 @@
|
|
1
|
-
unless Rails::Application.instance_methods.include?(:assets_manifest)
|
2
|
-
warn <<-END
|
3
|
-
[Swaggard] It seems you are using an api only rails setup, but swaggard
|
4
|
-
[Swaggard] neeeds sprockets in order to work so its going to require it.
|
5
|
-
[Swaggard] This might have undesired side effects, if thats not the case
|
6
|
-
[Swaggard] you can ignore this warning.
|
7
|
-
END
|
8
|
-
require 'sprockets/railtie'
|
9
|
-
end
|
10
|
-
|
11
1
|
module Swaggard
|
12
2
|
class Engine < ::Rails::Engine
|
13
3
|
isolate_namespace Swaggard
|
14
4
|
|
5
|
+
def rake?
|
6
|
+
File.basename($PROGRAM_NAME) == 'rake'
|
7
|
+
end
|
8
|
+
|
15
9
|
initializer 'swaggard.finisher_hook', after: :finisher_hook do |app|
|
16
10
|
app.reload_routes!
|
17
11
|
|
12
|
+
if Rails.env.development? && !rake? && !app.methods.include?(:assets_manifest)
|
13
|
+
warn <<~END
|
14
|
+
[Swaggard] It seems you are using an api only rails setup, but swaggard
|
15
|
+
[Swaggard] web app needs sprockets in order to work. Make sure to add
|
16
|
+
[Swaggard] require 'sprockets/railtie'.
|
17
|
+
[Swaggard] If you plan to use it
|
18
|
+
END
|
19
|
+
end
|
20
|
+
|
18
21
|
Swaggard.configure do |config|
|
19
22
|
unless config.controllers_path
|
20
23
|
config.controllers_path = "#{app.root}/app/controllers/**/*.rb"
|
@@ -4,23 +4,29 @@ require_relative '../swagger/tag'
|
|
4
4
|
module Swaggard
|
5
5
|
module Parsers
|
6
6
|
class Controller
|
7
|
-
|
8
7
|
def run(yard_objects)
|
9
|
-
|
8
|
+
tags = nil
|
10
9
|
operations = {}
|
11
10
|
|
12
11
|
yard_objects.each do |yard_object|
|
13
12
|
if yard_object.type == :class
|
14
|
-
|
15
|
-
elsif
|
13
|
+
tags = get_tags(yard_object)
|
14
|
+
elsif tags && yard_object.type == :method
|
16
15
|
name = yard_object.name
|
17
16
|
operations[name.to_s] = yard_object
|
18
17
|
end
|
19
18
|
end
|
20
19
|
|
21
|
-
return
|
20
|
+
return tags, operations
|
22
21
|
end
|
23
22
|
|
23
|
+
private
|
24
|
+
|
25
|
+
def get_tags(yard_object)
|
26
|
+
tags = yard_object.tags.select { |tag| tag.tag_name == 'tag' }
|
27
|
+
|
28
|
+
tags.map { |tag| Swagger::Tag.new(yard_object, tag) }
|
29
|
+
end
|
24
30
|
end
|
25
31
|
end
|
26
32
|
end
|
@@ -6,24 +6,33 @@ module Swaggard
|
|
6
6
|
class Models
|
7
7
|
|
8
8
|
def run(yard_objects)
|
9
|
-
definitions =
|
9
|
+
definitions = {}
|
10
10
|
|
11
11
|
yard_objects.each do |yard_object|
|
12
|
-
|
12
|
+
definition = parse_yard_object(yard_object)
|
13
13
|
|
14
|
-
definition =
|
14
|
+
definitions[definition.id] = definition if definition
|
15
|
+
end
|
16
|
+
|
17
|
+
definitions
|
18
|
+
end
|
15
19
|
|
20
|
+
def parse_yard_object(yard_object)
|
21
|
+
return unless yard_object.type == :class
|
22
|
+
|
23
|
+
Swagger::Definition.new(yard_object.path, ancestors: yard_object.inheritance_tree.map(&:path)).tap do |definition|
|
16
24
|
yard_object.tags.each do |tag|
|
17
|
-
|
18
|
-
|
25
|
+
case tag.tag_name
|
26
|
+
when 'attr'
|
27
|
+
property = Swagger::Property.new(tag)
|
28
|
+
definition.add_property(property)
|
29
|
+
when 'ignore_inherited'
|
30
|
+
definition.ignore_inherited = true
|
31
|
+
end
|
19
32
|
end
|
20
|
-
|
21
|
-
definitions << definition
|
22
33
|
end
|
23
|
-
|
24
|
-
definitions
|
25
34
|
end
|
26
35
|
|
27
36
|
end
|
28
37
|
end
|
29
|
-
end
|
38
|
+
end
|
@@ -3,13 +3,15 @@ module Swaggard
|
|
3
3
|
class Definition
|
4
4
|
|
5
5
|
attr_reader :id
|
6
|
-
attr_writer :description, :title
|
6
|
+
attr_writer :description, :title, :ignore_inherited
|
7
7
|
|
8
|
-
def initialize(id)
|
8
|
+
def initialize(id, ancestors: [])
|
9
9
|
@id = id
|
10
10
|
@title = ''
|
11
11
|
@properties = []
|
12
12
|
@description = ''
|
13
|
+
@ancestors = ancestors
|
14
|
+
@ignore_inherited = false
|
13
15
|
end
|
14
16
|
|
15
17
|
def add_property(property)
|
@@ -20,15 +22,35 @@ module Swaggard
|
|
20
22
|
@properties.empty?
|
21
23
|
end
|
22
24
|
|
23
|
-
def
|
25
|
+
def properties(definitions)
|
26
|
+
inherited_properties(definitions)
|
27
|
+
.concat(@properties)
|
28
|
+
.uniq { |property| property.id }
|
29
|
+
end
|
30
|
+
|
31
|
+
def inherited_properties(definitions)
|
32
|
+
return [] if @ignore_inherited
|
33
|
+
|
34
|
+
@ancestors.flat_map do |ancestor|
|
35
|
+
definition = definitions[ancestor]
|
36
|
+
|
37
|
+
next unless definition && definition.id != id
|
38
|
+
|
39
|
+
definition.properties(definitions)
|
40
|
+
end.compact
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_doc(definitions)
|
24
44
|
{}.tap do |doc|
|
25
45
|
doc['title'] = @title if @title.present?
|
26
46
|
doc['type'] = 'object'
|
27
47
|
|
28
48
|
doc['description'] = @description if @description.present?
|
29
49
|
|
30
|
-
|
31
|
-
|
50
|
+
all_properties = properties(definitions)
|
51
|
+
|
52
|
+
doc['properties'] = Hash[all_properties.map { |property| [property.id, property.to_doc] }]
|
53
|
+
required_properties = all_properties.select(&:required?).map(&:id)
|
32
54
|
doc['required'] = required_properties if required_properties.any?
|
33
55
|
end
|
34
56
|
|
@@ -32,7 +32,7 @@ module Swaggard
|
|
32
32
|
|
33
33
|
case yard_tag.tag_name
|
34
34
|
when 'operation_id'
|
35
|
-
@operation_id = value
|
35
|
+
@operation_id = "#{@tag.name}.#{value}"
|
36
36
|
when 'query_parameter'
|
37
37
|
@parameters << Parameters::Query.new(value)
|
38
38
|
when 'form_parameter'
|
@@ -92,8 +92,12 @@ module Swaggard
|
|
92
92
|
end
|
93
93
|
|
94
94
|
def definitions
|
95
|
-
@responses.map(&:definition).compact.
|
96
|
-
definitions
|
95
|
+
@responses.map(&:definition).compact.inject({}) do |definitions, definition|
|
96
|
+
definitions[definition.id] = definition
|
97
|
+
end.tap do |definitions|
|
98
|
+
next unless @body_parameter
|
99
|
+
|
100
|
+
definitions[@body_parameter.definition.id] = @body_parameter.definition
|
97
101
|
end
|
98
102
|
end
|
99
103
|
|
data/lib/swaggard/swagger/tag.rb
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
module Swaggard
|
2
2
|
module Swagger
|
3
3
|
class Tag
|
4
|
-
|
5
4
|
attr_accessor :name, :description
|
6
5
|
|
7
|
-
attr_reader :controller_class
|
6
|
+
attr_reader :controller_class, :controller_name, :route
|
8
7
|
|
9
|
-
def initialize(yard_object)
|
8
|
+
def initialize(yard_object, tag)
|
10
9
|
controller_name = "#{yard_object.namespace}::#{yard_object.name}"
|
11
10
|
|
12
11
|
@yard_name = yard_object.name
|
13
12
|
@controller_class = controller_name.constantize
|
14
|
-
|
15
|
-
tag = yard_object.tags.find { |tag| tag.tag_name == 'tag' }
|
13
|
+
@controller_name = controller_class.controller_path
|
16
14
|
|
17
15
|
@name = tag ? tag.text : "#{@controller_class.controller_path}"
|
16
|
+
@name, @route = @name.split(' ')
|
17
|
+
|
18
18
|
@description = yard_object.docstring || ''
|
19
19
|
end
|
20
20
|
|
@@ -24,7 +24,6 @@ module Swaggard
|
|
24
24
|
'description' => @description
|
25
25
|
}
|
26
26
|
end
|
27
|
-
|
28
27
|
end
|
29
28
|
end
|
30
29
|
end
|
data/lib/swaggard/version.rb
CHANGED
data/lib/swaggard.rb
CHANGED
@@ -38,6 +38,7 @@ module Swaggard
|
|
38
38
|
::YARD::Tags::Library.define_tag('Response description', :response_description)
|
39
39
|
::YARD::Tags::Library.define_tag('Response example', :response_example)
|
40
40
|
::YARD::Tags::Library.define_tag('Response header', :response_header)
|
41
|
+
::YARD::Tags::Library.define_tag('Ignore inherited attributes', :ignore_inherited)
|
41
42
|
end
|
42
43
|
|
43
44
|
def get_doc(host = nil)
|
@@ -61,21 +62,25 @@ module Swaggard
|
|
61
62
|
@api.ignore_put_if_patch! if Swaggard.configuration.ignore_put_if_patch_exists
|
62
63
|
end
|
63
64
|
|
65
|
+
def tag_matches?(tag, controller_name, path)
|
66
|
+
matches = tag.controller_name == controller_name
|
67
|
+
|
68
|
+
return matches unless tag.route.present?
|
69
|
+
|
70
|
+
matches && Regexp.new(tag.route).match?(path)
|
71
|
+
end
|
72
|
+
|
64
73
|
def build_operation(path, verb, route)
|
65
74
|
controller_name = route[:controller]
|
66
75
|
action_name = route[:action]
|
67
76
|
|
68
|
-
|
69
|
-
|
70
|
-
controller_tag = controllers[controller_name][:tag]
|
77
|
+
controller_tag, controller_operations = tags.find { |tag, _operations| tag_matches?(tag, controller_name, path) }
|
71
78
|
|
72
79
|
return unless controller_tag
|
73
80
|
|
74
|
-
return unless
|
75
|
-
|
76
|
-
return unless controllers[controller_name][:operations][action_name]
|
81
|
+
return unless controller_operations[action_name]
|
77
82
|
|
78
|
-
operation_yard_object =
|
83
|
+
operation_yard_object = controller_operations[action_name]
|
79
84
|
|
80
85
|
return unless operation_yard_object
|
81
86
|
|
@@ -100,23 +105,25 @@ module Swaggard
|
|
100
105
|
end
|
101
106
|
end
|
102
107
|
|
103
|
-
def
|
104
|
-
return @
|
108
|
+
def tags
|
109
|
+
return @tags if @tags
|
105
110
|
|
106
111
|
parser = Parsers::Controller.new
|
107
112
|
|
108
|
-
@
|
113
|
+
@tags = []
|
109
114
|
Dir[configuration.controllers_path].each do |file|
|
110
115
|
yard_objects = get_yard_objects(file)
|
111
116
|
|
112
|
-
|
117
|
+
tags, operations = parser.run(yard_objects)
|
113
118
|
|
114
|
-
next unless
|
119
|
+
next unless tags
|
115
120
|
|
116
|
-
|
121
|
+
tags.each do |tag|
|
122
|
+
@tags << [tag, operations]
|
123
|
+
end
|
117
124
|
end
|
118
125
|
|
119
|
-
@
|
126
|
+
@tags
|
120
127
|
end
|
121
128
|
|
122
129
|
def routes
|
@@ -129,12 +136,12 @@ module Swaggard
|
|
129
136
|
def parse_models
|
130
137
|
parser = Parsers::Models.new
|
131
138
|
|
132
|
-
definitions =
|
139
|
+
definitions = {}
|
133
140
|
configuration.models_paths.each do |path|
|
134
141
|
Dir[path].each do |file|
|
135
142
|
yard_objects = get_yard_objects(file)
|
136
143
|
|
137
|
-
definitions.
|
144
|
+
definitions.merge!(parser.run(yard_objects))
|
138
145
|
end
|
139
146
|
|
140
147
|
@api.definitions = definitions
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: swaggard
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adrian Gomez
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-12-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -19,7 +19,7 @@ dependencies:
|
|
19
19
|
version: '4.0'
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
22
|
+
version: '7.0'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -29,7 +29,7 @@ dependencies:
|
|
29
29
|
version: '4.0'
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
32
|
+
version: '7.0'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: sass-rails
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -192,7 +192,6 @@ files:
|
|
192
192
|
- spec/fixtures/dummy/config/application.rb
|
193
193
|
- spec/fixtures/dummy/config/environments/development.rb
|
194
194
|
- spec/fixtures/dummy/config/routes.rb
|
195
|
-
- spec/fixtures/dummy/log/development.log
|
196
195
|
- spec/fixtures/swagger_schema.json
|
197
196
|
- spec/integration/swaggard_spec.rb
|
198
197
|
- spec/spec_helper.rb
|
@@ -200,7 +199,7 @@ homepage: https://github.com/adrian-gomez/swaggard
|
|
200
199
|
licenses:
|
201
200
|
- MIT
|
202
201
|
metadata: {}
|
203
|
-
post_install_message:
|
202
|
+
post_install_message:
|
204
203
|
rdoc_options: []
|
205
204
|
require_paths:
|
206
205
|
- lib
|
@@ -215,19 +214,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
215
214
|
- !ruby/object:Gem::Version
|
216
215
|
version: '0'
|
217
216
|
requirements: []
|
218
|
-
rubygems_version: 3.
|
219
|
-
signing_key:
|
217
|
+
rubygems_version: 3.2.15
|
218
|
+
signing_key:
|
220
219
|
specification_version: 4
|
221
220
|
summary: 'Swaggard: Swagger Rails REST API doc using yard YARD'
|
222
221
|
test_files:
|
223
|
-
- spec/
|
224
|
-
- spec/integration/swaggard_spec.rb
|
225
|
-
- spec/fixtures/swagger_schema.json
|
226
|
-
- spec/fixtures/dummy/app/controllers/pets_controller.rb
|
227
|
-
- spec/fixtures/dummy/app/controllers/application_controller.rb
|
222
|
+
- spec/fixtures/api.json
|
228
223
|
- spec/fixtures/dummy/app/controllers/admin/pets_controller.rb
|
229
|
-
- spec/fixtures/dummy/
|
230
|
-
- spec/fixtures/dummy/
|
224
|
+
- spec/fixtures/dummy/app/controllers/application_controller.rb
|
225
|
+
- spec/fixtures/dummy/app/controllers/pets_controller.rb
|
231
226
|
- spec/fixtures/dummy/config/application.rb
|
232
|
-
- spec/fixtures/dummy/
|
233
|
-
- spec/fixtures/
|
227
|
+
- spec/fixtures/dummy/config/environments/development.rb
|
228
|
+
- spec/fixtures/dummy/config/routes.rb
|
229
|
+
- spec/fixtures/swagger_schema.json
|
230
|
+
- spec/integration/swaggard_spec.rb
|
231
|
+
- spec/spec_helper.rb
|
File without changes
|