zero-rails_openapi 1.4.0 → 1.4.1
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/CHANGELOG.md +74 -0
- data/Gemfile.lock +8 -10
- data/README.md +48 -34
- data/README_zh.md +747 -1
- data/documentation/examples/auto_gen_doc.rb +1 -1
- data/documentation/examples/examples_controller.rb +14 -0
- data/documentation/examples/goods_doc.rb +5 -6
- data/documentation/examples/open_api.rb +1 -52
- data/lib/oas_objs/helpers.rb +0 -1
- data/lib/oas_objs/param_obj.rb +2 -5
- data/lib/oas_objs/schema_obj.rb +38 -89
- data/lib/oas_objs/schema_obj_helpers.rb +68 -0
- data/lib/open_api/config.rb +8 -0
- data/lib/open_api/config_dsl.rb +4 -4
- data/lib/open_api/dsl.rb +4 -4
- data/lib/open_api/dsl/api_info_obj.rb +1 -1
- data/lib/open_api/dsl/{ctrl_info_obj.rb → components.rb} +3 -2
- data/lib/open_api/dsl/helpers.rb +22 -18
- data/lib/open_api/generator.rb +4 -21
- data/lib/open_api/version.rb +1 -1
- data/zero-rails_openapi.gemspec +4 -4
- metadata +9 -9
data/lib/open_api/dsl.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'open_api/dsl/api_info_obj'
|
2
|
-
require 'open_api/dsl/
|
2
|
+
require 'open_api/dsl/components'
|
3
3
|
|
4
4
|
module OpenApi
|
5
5
|
module DSL
|
@@ -25,18 +25,17 @@ module OpenApi
|
|
25
25
|
|
26
26
|
def components &block
|
27
27
|
apis_tag if @_ctrl_infos.nil?
|
28
|
-
current_ctrl = @_ctrl_infos[:components] =
|
28
|
+
current_ctrl = @_ctrl_infos[:components] = Components.new
|
29
29
|
current_ctrl.instance_eval(&block)
|
30
30
|
current_ctrl._process_objs
|
31
31
|
end
|
32
32
|
|
33
|
-
def api action, summary = '', http: nil,
|
33
|
+
def api action, summary = '', http: nil, skip: [ ], use: [ ], &block
|
34
34
|
apis_tag if @_ctrl_infos.nil?
|
35
35
|
# select the routing info (corresponding to the current method) from routing list.
|
36
36
|
action_path = "#{@_ctrl_path ||= controller_path}##{action}"
|
37
37
|
routes_info = ctrl_routes_list&.select { |api| api[:action_path].match?(/^#{action_path}$/) }&.first
|
38
38
|
pp "[ZRO Warning] Routing mapping failed: #{@_ctrl_path}##{action}" and return if routes_info.nil?
|
39
|
-
Generator.generate_builder_file(action_path, builder)
|
40
39
|
|
41
40
|
api = ApiInfoObj.new(action_path, skip: Array(skip), use: Array(use))
|
42
41
|
.merge! description: '', summary: summary, operationId: action, tags: [@_apis_tag],
|
@@ -50,6 +49,7 @@ module OpenApi
|
|
50
49
|
path = (@_api_infos ||= { })[routes_info[:path]] ||= { }
|
51
50
|
http_verbs = (http || routes_info[:http_verb]).split('|')
|
52
51
|
http_verbs.each { |verb| path[verb] = api }
|
52
|
+
api
|
53
53
|
end
|
54
54
|
|
55
55
|
# method could be symbol array, like: %i[ .. ]
|
@@ -101,7 +101,7 @@ module OpenApi
|
|
101
101
|
body! :form, desc, hash
|
102
102
|
end
|
103
103
|
|
104
|
-
# TODO: 这种情况下 form 和 file 无法共存,需要解决(通过
|
104
|
+
# TODO: 这种情况下 form 和 file 无法共存,需要解决(通过 combined?)
|
105
105
|
def file media_type, desc = '', hash = { type: File }
|
106
106
|
body media_type, desc, hash
|
107
107
|
end
|
@@ -2,17 +2,18 @@ require 'open_api/dsl/common_dsl'
|
|
2
2
|
|
3
3
|
module OpenApi
|
4
4
|
module DSL
|
5
|
-
class
|
5
|
+
class Components < Hash
|
6
6
|
include DSL::CommonDSL
|
7
7
|
include DSL::Helpers
|
8
8
|
|
9
9
|
def schema component_key, type = nil, one_of: nil, all_of: nil, any_of: nil, not: nil, **schema_hash
|
10
10
|
(schema_hash = type) and (type = type.delete(:type)) if type.is_a?(Hash) && type.key?(:type)
|
11
11
|
type = schema_hash[:type] if type.nil?
|
12
|
+
type = load_schema component_key if component_key.try(:superclass) == Config.active_record_base && type.nil?
|
12
13
|
|
13
14
|
combined_schema = one_of || all_of || any_of || (_not = binding.local_variable_get(:not))
|
14
15
|
combined_schema = CombinedSchema.new(one_of: one_of, all_of: all_of, any_of: any_of, _not: _not) if combined_schema
|
15
|
-
(self[:schemas] ||= { })[component_key] = combined_schema&.process || SchemaObj.new(type, schema_hash).process
|
16
|
+
(self[:schemas] ||= { })[component_key.to_s.to_sym] = combined_schema&.process || SchemaObj.new(type, schema_hash).process
|
16
17
|
end
|
17
18
|
arrow_enable :schema
|
18
19
|
|
data/lib/open_api/dsl/helpers.rb
CHANGED
@@ -12,28 +12,32 @@ module OpenApi
|
|
12
12
|
# (3) jbuilder file: https://github.com/zhandao/zero-rails/blob/mster/app/views/api/v1/goods/index.json.jbuilder
|
13
13
|
# In a word, BuilderSupport let you control the `output fields and nested association infos` very easily.
|
14
14
|
if model.respond_to? :show_attrs
|
15
|
-
|
16
|
-
model.show_attrs.map do |attr|
|
17
|
-
if columns.include?(attr)
|
18
|
-
index = columns.index(attr)
|
19
|
-
type = model.columns[index].sql_type_metadata.type.to_s.camelize
|
20
|
-
type = 'DateTime' if type == 'Datetime'
|
21
|
-
{ attr => Object.const_get(type) }
|
22
|
-
elsif attr.match?(/_info/)
|
23
|
-
# TODO: 如何获知关系是 many?因为不能只判断结尾是否 ‘s’
|
24
|
-
assoc_model = Object.const_get(attr.to_s.split('_').first.singularize.camelize)
|
25
|
-
{ attr => load_schema(assoc_model) }
|
26
|
-
end rescue next
|
27
|
-
end
|
15
|
+
_load_schema_based_on_show_attr(model)
|
28
16
|
else
|
29
|
-
model.columns.map
|
30
|
-
type = column.sql_type_metadata.type.to_s.camelize
|
31
|
-
type = 'DateTime' if type == 'Datetime'
|
32
|
-
{ column.name.to_sym => Object.const_get(type) }
|
33
|
-
end
|
17
|
+
model.columns.map { |column| _type_mapping(column) }
|
34
18
|
end.compact.reduce({ }, :merge) rescue ''
|
35
19
|
end
|
36
20
|
|
21
|
+
def _type_mapping(column)
|
22
|
+
type = column.sql_type_metadata.type.to_s.camelize
|
23
|
+
type = 'DateTime' if type == 'Datetime'
|
24
|
+
{ column.name.to_sym => Object.const_get(type) }
|
25
|
+
end
|
26
|
+
|
27
|
+
def _load_schema_based_on_show_attr(model)
|
28
|
+
columns = model.column_names.map(&:to_sym)
|
29
|
+
model.show_attrs.map do |attr|
|
30
|
+
if columns.include?(attr)
|
31
|
+
index = columns.index(attr)
|
32
|
+
_type_mapping(model.columns[index])
|
33
|
+
elsif attr.match?(/_info/)
|
34
|
+
# TODO: 如何获知关系是 many?因为不能只判断结尾是否 ‘s’
|
35
|
+
assoc_model = Object.const_get(attr.to_s.split('_').first.singularize.camelize)
|
36
|
+
{ attr => load_schema(assoc_model) }
|
37
|
+
end rescue next
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
37
41
|
# Arrow Writing:
|
38
42
|
# response :RespComponent => [ '200', 'success', :json ]
|
39
43
|
# It is equivalent to:
|
data/lib/open_api/generator.rb
CHANGED
@@ -13,8 +13,7 @@ module OpenApi
|
|
13
13
|
# It causes problems, such as making `skip_before_action` not working.
|
14
14
|
file.sub('./app/controllers/', '').sub('.rb', '').camelize.constantize
|
15
15
|
end
|
16
|
-
|
17
|
-
Dir['./app/**/*_doc.rb'].each { |file| require file }
|
16
|
+
Dir[*Array(Config.doc_location)].each { |file| require file }
|
18
17
|
if doc_name.present?
|
19
18
|
[{ doc_name => generate_doc(doc_name) }]
|
20
19
|
else
|
@@ -27,9 +26,8 @@ module OpenApi
|
|
27
26
|
doc = { openapi: '3.0.0' }.merge(settings.slice :info, :servers).merge(
|
28
27
|
security: settings[:global_security], tags: [ ], paths: { },
|
29
28
|
components: {
|
30
|
-
securitySchemes:
|
31
|
-
|
32
|
-
}
|
29
|
+
securitySchemes: { }, schemas: { }, parameters: { }, requestBodies: { }
|
30
|
+
}.merge(settings[:components])
|
33
31
|
)
|
34
32
|
|
35
33
|
settings[:root_controller].descendants.each do |ctrl|
|
@@ -37,7 +35,7 @@ module OpenApi
|
|
37
35
|
next if ctrl_infos.nil?
|
38
36
|
doc[:paths].merge! ctrl.instance_variable_get('@_api_infos') || { }
|
39
37
|
doc[:tags] << ctrl_infos[:tag]
|
40
|
-
doc[:components].merge!
|
38
|
+
doc[:components].merge!(ctrl_infos[:components] || { }) { |_key, l, r| l.merge(r) }
|
41
39
|
OpenApi.paths_index[ctrl.instance_variable_get('@_ctrl_path')] = doc_name
|
42
40
|
end
|
43
41
|
doc[:components].delete_if { |_, v| v.blank? }
|
@@ -61,21 +59,6 @@ module OpenApi
|
|
61
59
|
end
|
62
60
|
end
|
63
61
|
|
64
|
-
def self.generate_builder_file(action_path, builder)
|
65
|
-
return unless Config.generate_jbuilder_file
|
66
|
-
return if builder.nil?
|
67
|
-
|
68
|
-
path, action = action_path.split('#')
|
69
|
-
dir_path = "app/views/#{path}"
|
70
|
-
FileUtils.mkdir_p dir_path
|
71
|
-
file_path = "#{dir_path}/#{action}.json.jbuilder"
|
72
|
-
|
73
|
-
if Config.overwrite_jbuilder_file || !File.exist?(file_path)
|
74
|
-
File.open(file_path, 'w') { |file| file.write Config.jbuilder_templates[builder] }
|
75
|
-
puts "[ZRO] JBuilder file has been generated: #{path}/#{action}"
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
62
|
def self.routes_list
|
80
63
|
routes =
|
81
64
|
if (f = Config.rails_routes_file)
|
data/lib/open_api/version.rb
CHANGED
data/zero-rails_openapi.gemspec
CHANGED
@@ -9,10 +9,8 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["zhandao"]
|
10
10
|
spec.email = ["x@skippingcat.com"]
|
11
11
|
|
12
|
-
spec.summary = %q{
|
13
|
-
spec.description = %q{
|
14
|
-
documentation JSON file for Rails application,
|
15
|
-
then you can use Swagger-UI 3.2.0+ to show the documentation.}
|
12
|
+
spec.summary = %q{Concise DSL for generating OpenAPI3 documentation.}
|
13
|
+
spec.description = %q{Concise DSL for generating OpenAPI Specification 3 (OAS3) JSON documentation for Rails application.}
|
16
14
|
spec.homepage = "https://github.com/zhandao/zero-rails_openapi"
|
17
15
|
spec.license = "MIT"
|
18
16
|
|
@@ -29,4 +27,6 @@ Gem::Specification.new do |spec|
|
|
29
27
|
|
30
28
|
spec.add_runtime_dependency "rails", ">= 3"
|
31
29
|
spec.add_runtime_dependency "activesupport", ">= 3"
|
30
|
+
|
31
|
+
# spec.post_install_message = ""
|
32
32
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zero-rails_openapi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.
|
4
|
+
version: 1.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- zhandao
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-12-
|
11
|
+
date: 2017-12-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -80,10 +80,8 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '3'
|
83
|
-
description:
|
84
|
-
|
85
|
-
documentation JSON file for Rails application,
|
86
|
-
then you can use Swagger-UI 3.2.0+ to show the documentation.
|
83
|
+
description: Concise DSL for generating OpenAPI Specification 3 (OAS3) JSON documentation
|
84
|
+
for Rails application.
|
87
85
|
email:
|
88
86
|
- x@skippingcat.com
|
89
87
|
executables: []
|
@@ -94,6 +92,7 @@ files:
|
|
94
92
|
- ".rspec"
|
95
93
|
- ".rubocop.yml"
|
96
94
|
- ".travis.yml"
|
95
|
+
- CHANGELOG.md
|
97
96
|
- CODE_OF_CONDUCT.md
|
98
97
|
- Gemfile
|
99
98
|
- Gemfile.lock
|
@@ -119,13 +118,14 @@ files:
|
|
119
118
|
- lib/oas_objs/request_body_obj.rb
|
120
119
|
- lib/oas_objs/response_obj.rb
|
121
120
|
- lib/oas_objs/schema_obj.rb
|
121
|
+
- lib/oas_objs/schema_obj_helpers.rb
|
122
122
|
- lib/open_api.rb
|
123
123
|
- lib/open_api/config.rb
|
124
124
|
- lib/open_api/config_dsl.rb
|
125
125
|
- lib/open_api/dsl.rb
|
126
126
|
- lib/open_api/dsl/api_info_obj.rb
|
127
127
|
- lib/open_api/dsl/common_dsl.rb
|
128
|
-
- lib/open_api/dsl/
|
128
|
+
- lib/open_api/dsl/components.rb
|
129
129
|
- lib/open_api/dsl/helpers.rb
|
130
130
|
- lib/open_api/generator.rb
|
131
131
|
- lib/open_api/version.rb
|
@@ -150,8 +150,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
150
150
|
version: '0'
|
151
151
|
requirements: []
|
152
152
|
rubyforge_project:
|
153
|
-
rubygems_version: 2.6.
|
153
|
+
rubygems_version: 2.6.12
|
154
154
|
signing_key:
|
155
155
|
specification_version: 4
|
156
|
-
summary:
|
156
|
+
summary: Concise DSL for generating OpenAPI3 documentation.
|
157
157
|
test_files: []
|