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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fab58d6a912611eb51d9d86bc69401c5feb70f06
|
4
|
+
data.tar.gz: 2aa24ae7d92823d075cbb21acf09949e365d13ab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c321e853c95bad0cc5324c9719b3e610c54b2bd4bb18190b2876d091a115b3d90f3b6450645684606ae295c230ab700bca3fa7461fc40a057753376ab6651a02
|
7
|
+
data.tar.gz: 4e273a9871cd4e8078bad7cc56a7c6b5e6e40a26825f00e57cc28783d61cf49d7557829b76b7a55e6c3fd3297efc0b1bd124a6237685c4002599812ce55814bb
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Version Changelog
|
2
|
+
|
3
|
+
|
4
|
+
## [1.4.1] - 2017/12/6 - [view diff](https://github.com/zhandao/zero-rails_openapi/compare/v1.4.0...v1.4.1)
|
5
|
+
|
6
|
+
### Feature
|
7
|
+
|
8
|
+
1. Pass a ActiveRecord class constant to the `schema`,
|
9
|
+
it will automatically read the db schema to generate the component.
|
10
|
+
|
11
|
+
### Fixed
|
12
|
+
|
13
|
+
1. Fix: Components defined in the controller overwrite the ones defined in the configuration.
|
14
|
+
|
15
|
+
### Changed
|
16
|
+
|
17
|
+
1. Remove JBuilder automatic generator.
|
18
|
+
2. Refactoring based on CodeClimate.
|
19
|
+
3. Rename `CtrlInfoObj` to `Components`.
|
20
|
+
|
21
|
+
### Added
|
22
|
+
|
23
|
+
1. Update README.
|
24
|
+
2. Add CHANGELOG.
|
25
|
+
3. `doc_location` can be configured.
|
26
|
+
|
27
|
+
## [1.4.0] - 2017/12/3 - [view diff](https://github.com/zhandao/zero-rails_openapi/compare/v1.3.3...v1.4.0)
|
28
|
+
|
29
|
+
### Fixed
|
30
|
+
|
31
|
+
1. Fix controller's require question in `generate_docs`.
|
32
|
+
|
33
|
+
### Feature
|
34
|
+
|
35
|
+
1. Support CombinedSchema, like `one_of`, `any_of`..
|
36
|
+
2. Authentication and Authorization DSL, for Defining Security Scheme and Applying Security.
|
37
|
+
3. The ability to identify multi HTTP verbs.
|
38
|
+
4. Support read files to get routes information. (Config.rails_routes_file)
|
39
|
+
|
40
|
+
### Changed
|
41
|
+
|
42
|
+
1. **[IMPORTANT]** DSL `open_api` => `api`.
|
43
|
+
2. Config.register_docs => Config.open_api_docs.
|
44
|
+
3. Document Definition DSL `api` => `open_api`.
|
45
|
+
4. Use module instance variables instead of global variables.
|
46
|
+
5. Is refactoring based on `rubocop` by hand.
|
47
|
+
|
48
|
+
### Added
|
49
|
+
|
50
|
+
1. Also support `api :name, type: String`.
|
51
|
+
(You have to write this before `api :name, String`)
|
52
|
+
2. Support designated http method in `api`.
|
53
|
+
3. The completion of the basic README.
|
54
|
+
|
55
|
+
## [1.3.2 & 1.3.3] - 2017/11/10,21 - [view diff](https://github.com/zhandao/zero-rails_openapi/compare/v1.3.1...v1.3.3)
|
56
|
+
|
57
|
+
### Feature
|
58
|
+
|
59
|
+
1. Document Definition DSL.
|
60
|
+
2. Parameter `order`:
|
61
|
+
Support to use `sort` to specify the order in which parameters are arranged.
|
62
|
+
This is useful when you dry your DSL.
|
63
|
+
3. Parameter `examples`.
|
64
|
+
|
65
|
+
### Added
|
66
|
+
|
67
|
+
1. Rewrote README.
|
68
|
+
|
69
|
+
## [1.3.1] - 2017/11/5 - [view diff](https://github.com/zhandao/zero-rails_openapi/compare/v1.3.0...v1.3.1)
|
70
|
+
|
71
|
+
1. Refactoring based on bbatsov and Airbnb's style guide, more readable.
|
72
|
+
2. Support response override by using `override_response`.
|
73
|
+
3. Separate `apis_set` into `apis_tag` and `components`.
|
74
|
+
4. Support simplify param DSL with `do_* by: { }` method.
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
zero-rails_openapi (1.4.
|
4
|
+
zero-rails_openapi (1.4.1)
|
5
5
|
activesupport (>= 3)
|
6
6
|
rails (>= 3)
|
7
7
|
|
@@ -48,29 +48,27 @@ GEM
|
|
48
48
|
arel (8.0.0)
|
49
49
|
builder (3.2.3)
|
50
50
|
concurrent-ruby (1.0.5)
|
51
|
-
crass (1.0.
|
51
|
+
crass (1.0.3)
|
52
52
|
diff-lcs (1.3)
|
53
53
|
erubi (1.7.0)
|
54
54
|
globalid (0.4.1)
|
55
55
|
activesupport (>= 4.2.0)
|
56
|
-
i18n (0.9.
|
56
|
+
i18n (0.9.1)
|
57
57
|
concurrent-ruby (~> 1.0)
|
58
58
|
loofah (2.1.1)
|
59
59
|
crass (~> 1.0.2)
|
60
60
|
nokogiri (>= 1.5.9)
|
61
|
-
mail (2.
|
62
|
-
|
61
|
+
mail (2.7.0)
|
62
|
+
mini_mime (>= 0.1.1)
|
63
63
|
method_source (0.9.0)
|
64
|
-
|
65
|
-
mime-types-data (~> 3.2015)
|
66
|
-
mime-types-data (3.2016.0521)
|
64
|
+
mini_mime (1.0.0)
|
67
65
|
mini_portile2 (2.3.0)
|
68
66
|
minitest (5.10.3)
|
69
67
|
nio4r (2.1.0)
|
70
68
|
nokogiri (1.8.1)
|
71
69
|
mini_portile2 (~> 2.3.0)
|
72
70
|
rack (2.0.3)
|
73
|
-
rack-test (0.
|
71
|
+
rack-test (0.8.2)
|
74
72
|
rack (>= 1.0, < 3)
|
75
73
|
rails (5.1.4)
|
76
74
|
actioncable (= 5.1.4)
|
@@ -122,7 +120,7 @@ GEM
|
|
122
120
|
thread_safe (~> 0.1)
|
123
121
|
websocket-driver (0.6.5)
|
124
122
|
websocket-extensions (>= 0.1.0)
|
125
|
-
websocket-extensions (0.1.
|
123
|
+
websocket-extensions (0.1.3)
|
126
124
|
|
127
125
|
PLATFORMS
|
128
126
|
ruby
|
data/README.md
CHANGED
@@ -2,13 +2,14 @@
|
|
2
2
|
|
3
3
|
[](https://badge.fury.io/rb/zero-rails_openapi)
|
4
4
|
[](https://travis-ci.org/zhandao/zero-rails_openapi)
|
5
|
+
[](https://codeclimate.com/github/zhandao/zero-rails_openapi/maintainability)
|
5
6
|
|
6
|
-
|
7
|
+
Concise DSL for generating OpenAPI Specification 3 (**OAS3**, formerly Swagger3) JSON documentation for Rails application,
|
7
8
|
then you can use Swagger UI 3.2.0+ to show the documentation.
|
8
9
|
|
9
10
|
## Contributing
|
10
11
|
|
11
|
-
**Hi, here is ZhanDao = ▽ =
|
12
|
+
**Hi, here is ZhanDao = ▽ =
|
12
13
|
I think it's a very useful tool when you want to write API document clearly.
|
13
14
|
I'm looking forward to your issue and PR, thanks!**
|
14
15
|
|
@@ -18,19 +19,19 @@
|
|
18
19
|
- [Installation](#installation)
|
19
20
|
- [Configure](#configure)
|
20
21
|
- [Usage - DSL](#usage---dsl)
|
21
|
-
- [DSL methods inside `
|
22
|
-
- [DSL methods inside `components`'s block](#dsl-methods-inside-componentss-block-code-source
|
22
|
+
- [DSL methods inside `api` and `api_dry`'s block](#dsl-methods-inside-api-and-api_drys-block)
|
23
|
+
- [DSL methods inside `components`'s block](#dsl-methods-inside-componentss-block-code-source)
|
23
24
|
- [Usage - Generate JSON documentation file](#usage---generate-json-documentation-file)
|
24
25
|
- [Usage - Use Swagger UI(very beautiful web page) to show your Documentation](#usage---use-swagger-uivery-beautiful-web-page-to-show-your-documentation)
|
25
26
|
- [Tricks](#tricks)
|
26
27
|
- [Write DSL somewhere else](#trick1---write-the-dsl-somewhere-else)
|
27
28
|
- [Global DRYing](#trick2---global-drying)
|
28
29
|
- [Auto generate description](#trick3---auto-generate-description)
|
29
|
-
- [Skip or Use parameters define in api_dry](#trick4---skip-or-use-parameters-define-in-api_dry)
|
30
|
+
- [Skip or Use parameters define in `api_dry`](#trick4---skip-or-use-parameters-define-in-api_dry)
|
30
31
|
- [Atuo Generate index/show Actions's Responses Based on DB Schema](#trick5---auto-generate-indexshow-actionss-response-types-based-on-db-schema)
|
31
|
-
- [Combined Schema (
|
32
|
+
- [Combined Schema (one_of / all_of / any_of / not)](#trick6---combined-schema-one_of--all_of--any_of--not)
|
32
33
|
- [Troubleshooting](#troubleshooting)
|
33
|
-
- [About `OpenApi.docs` and `OpenApi.paths_index`]()
|
34
|
+
- [About `OpenApi.docs` and `OpenApi.paths_index`](#about-openapidocs-and-openapipaths_index)
|
34
35
|
|
35
36
|
## About OAS
|
36
37
|
|
@@ -38,7 +39,7 @@
|
|
38
39
|
|
39
40
|
You can getting started from [swagger.io](https://swagger.io/docs/specification/basic-structure/)
|
40
41
|
|
41
|
-
**I suggest you should understand OAS3's basic structure at least.**
|
42
|
+
**I suggest you should understand OAS3's basic structure at least.**
|
42
43
|
such as component (can help you reuse DSL code, when your apis are used with the
|
43
44
|
same data structure).
|
44
45
|
|
@@ -62,9 +63,9 @@
|
|
62
63
|
|
63
64
|
## Configure
|
64
65
|
|
65
|
-
Create an initializer, configure ZRO and define your
|
66
|
+
Create an initializer, configure ZRO and define your OpenApi documents.
|
66
67
|
|
67
|
-
This is the simplest
|
68
|
+
This is the simplest example:
|
68
69
|
|
69
70
|
```ruby
|
70
71
|
# config/initializers/open_api.rb
|
@@ -75,7 +76,8 @@
|
|
75
76
|
c.file_output_path = 'public/open_api'
|
76
77
|
|
77
78
|
c.open_api_docs = {
|
78
|
-
|
79
|
+
# The definition of the document `homepage`.
|
80
|
+
homepage: {
|
79
81
|
# [REQUIRED] ZRO will scan all the descendants of root_controller, then generate their docs.
|
80
82
|
root_controller: Api::V1::BaseController,
|
81
83
|
|
@@ -95,10 +97,9 @@
|
|
95
97
|
}
|
96
98
|
end
|
97
99
|
```
|
98
|
-
The following global configuration and component of OAS are allow to be set in the initializer:
|
99
|
-
Server Object / Security Scheme Object / Security Requirement Object ...
|
100
100
|
|
101
|
-
In addition to
|
101
|
+
In addition to directly using Hash,
|
102
|
+
you can also use DSL to define the document information:
|
102
103
|
|
103
104
|
```ruby
|
104
105
|
# config/initializers/open_api.rb
|
@@ -114,11 +115,11 @@
|
|
114
115
|
|
115
116
|
For more detailed configuration: [open_api.rb](documentation/examples/open_api.rb)
|
116
117
|
See all the settings you can configure: [config.rb](lib/open_api/config.rb)
|
117
|
-
See all the
|
118
|
+
See all the Document Definition DSL: [config_dsl.rb](lib/open_api/config_dsl.rb)
|
118
119
|
|
119
120
|
## Usage - DSL
|
120
121
|
|
121
|
-
### First of all, include DSL to your base
|
122
|
+
### First of all, `include OpenApi::DSL` to your base class (which is for writing docs), for example:
|
122
123
|
|
123
124
|
```ruby
|
124
125
|
# app/controllers/api/api_controller.rb
|
@@ -143,9 +144,9 @@
|
|
143
144
|
For more example, see [goods_doc.rb](documentation/examples/goods_doc.rb), and
|
144
145
|
[examples_controller.rb](documentation/examples/examples_controller.rb)
|
145
146
|
|
146
|
-
### DSL
|
147
|
+
### DSL as class methods ([source code](lib/open_api/dsl.rb))
|
147
148
|
|
148
|
-
#### (1) `ctrl_path` (controller path) [optional]
|
149
|
+
#### (1) `ctrl_path` (controller path) [optional if you're writing DSL in controller]
|
149
150
|
|
150
151
|
```ruby
|
151
152
|
# method signature
|
@@ -218,16 +219,17 @@
|
|
218
219
|
|
219
220
|
```ruby
|
220
221
|
# method signature
|
221
|
-
api(action, summary = '',
|
222
|
+
api(action, summary = '', skip: [ ], use: [ ], &block)
|
222
223
|
# usage
|
223
|
-
api :index, '(SUMMARY) this api blah blah ...',
|
224
|
+
api :index, '(SUMMARY) this api blah blah ...', # block ...
|
224
225
|
```
|
225
|
-
If you pass `builder`, and `generate_jbuilder_file` is set to `true` (in your initializer),
|
226
|
-
ZRO will generate JBuilder file by using specified template called `index`.
|
227
|
-
About template settings, see: [open_api.rb](documentation/examples/open_api.rb)
|
228
226
|
|
229
227
|
`use` and `skip` options: to use or skip the parameters defined in `api_dry`.
|
230
228
|
|
229
|
+
[Note] JBuilder file automatic generator has been removed,
|
230
|
+
If you need this function, please refer to [here](https://github.com/zhandao/zero-rails/tree/master/lib/generators/jubilder/dsl.rb)
|
231
|
+
to implement a lib.
|
232
|
+
|
231
233
|
```ruby
|
232
234
|
api :show, 'summary', use: [:id] # => it will only take :id from DRYed result.
|
233
235
|
```
|
@@ -354,7 +356,7 @@
|
|
354
356
|
}
|
355
357
|
```
|
356
358
|
|
357
|
-
[This trick show you how to define combined schema (by using `one_of` ..)]()
|
359
|
+
[This trick show you how to define combined schema (by using `one_of` ..)](#trick6---combined-schema-one-of--all-of--any-of--not)
|
358
360
|
|
359
361
|
[**>> More About `param` DSL <<**](documentation/parameter.md)
|
360
362
|
|
@@ -535,27 +537,34 @@
|
|
535
537
|
server 'http://localhost:3000', 'local'
|
536
538
|
```
|
537
539
|
|
538
|
-
### DSL methods inside [components]()'s block ([code source](lib/open_api/dsl/
|
540
|
+
### DSL methods inside [components]()'s block ([code source](lib/open_api/dsl/components.rb))
|
539
541
|
|
540
542
|
(Here corresponds to OAS [Components Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#componentsObject))
|
541
543
|
|
542
|
-
|
543
|
-
|
544
|
+
Inside `components`'s block,
|
545
|
+
you can use the same DSL as [[DSL methods inside `api` and `api_dry`'s block]](#dsl-methods-inside-api-and-api_drys-block).
|
546
|
+
But there are two differences:
|
547
|
+
|
548
|
+
(1) Each method needs to pass one more parameter `component_key`
|
549
|
+
(in the first parameter position),
|
550
|
+
this will be used as the reference name for the component.
|
544
551
|
|
545
552
|
```ruby
|
546
553
|
query! :UidQuery, :uid, String
|
547
554
|
```
|
548
555
|
This writing is feasible but not recommended,
|
549
|
-
because component's key and parameter's name
|
556
|
+
because component's key and parameter's name seem easy to confuse.
|
550
557
|
The recommended writing is:
|
551
558
|
|
552
559
|
```ruby
|
553
560
|
query! :UidQuery => [:uid, String]
|
554
561
|
```
|
555
562
|
|
563
|
+
(2) You can use `schema` to define a Schema Component.
|
564
|
+
|
556
565
|
```ruby
|
557
566
|
# method signature
|
558
|
-
schema(component_key, type, schema_hash)
|
567
|
+
schema(component_key, type = nil, one_of: nil, all_of: nil, any_of: nil, not: nil, **schema_hash)
|
559
568
|
# usage
|
560
569
|
schema :Dog => [ String, desc: 'dogee' ] # <= schema_type is `String`
|
561
570
|
# advance usage
|
@@ -569,9 +578,13 @@
|
|
569
578
|
]
|
570
579
|
# or (unrecommended)
|
571
580
|
schema :Dog, { id!: Integer, name: String }, dft: { id: 1, name: 'pet' }, desc: 'dogee'
|
581
|
+
#
|
582
|
+
# pass a ActiveRecord class constant as `component_key`,
|
583
|
+
# it will automatically read the db schema to generate the component.
|
584
|
+
schema User # easy! And the component_key will be :User
|
572
585
|
```
|
573
586
|
[1] see: [Type](documentation/parameter.md#type-schema_type)
|
574
|
-
|
587
|
+
|
575
588
|
## Usage - Generate JSON Documentation File
|
576
589
|
|
577
590
|
Use `OpenApi.write_docs`:
|
@@ -623,7 +636,8 @@
|
|
623
636
|
end
|
624
637
|
```
|
625
638
|
|
626
|
-
Notes:
|
639
|
+
Notes: file name ends in `_doc.rb` by default, but you can change via `Config.doc_location`
|
640
|
+
(it should be file paths, defaults to `./app/**/*_doc.rb`).
|
627
641
|
|
628
642
|
### Trick2 - Global DRYing
|
629
643
|
|
@@ -669,7 +683,7 @@
|
|
669
683
|
|
670
684
|
Pass `skip: []` and `use: []` to `api` like following code:
|
671
685
|
```ruby
|
672
|
-
api :index, 'desc',
|
686
|
+
api :index, 'desc', skip: [ :Token ]
|
673
687
|
```
|
674
688
|
|
675
689
|
Look at this [file](documentation/examples/goods_doc.rb) to learn more.
|
@@ -680,7 +694,7 @@
|
|
680
694
|
|
681
695
|
See this [file](documentation/examples/auto_gen_doc.rb#L51) for uasge information.
|
682
696
|
|
683
|
-
### Trick6 - Combined Schema (
|
697
|
+
### Trick6 - Combined Schema (one_of / all_of / any_of / not)
|
684
698
|
|
685
699
|
```ruby
|
686
700
|
query :combination, one_of: [ :GoodSchema, String, { type: Integer, desc: 'integer input'}]
|
@@ -709,7 +723,7 @@
|
|
709
723
|
- **Report error when require `routes.rb`?***
|
710
724
|
1. Run `rails routes`.
|
711
725
|
2. Copy the output to a file, for example `config/routes.txt`.
|
712
|
-
|
726
|
+
Ignore the file `config/routes.txt`.
|
713
727
|
3. Put `c.rails_routes_file = 'config/routes.txt'` to your ZRO config.
|
714
728
|
|
715
729
|
|
data/README_zh.md
CHANGED
@@ -1 +1,747 @@
|
|
1
|
-
|
1
|
+
# ZRO: Rails 应用 OpenApi3 JSON 文档生成器
|
2
|
+
|
3
|
+
[](https://badge.fury.io/rb/zero-rails_openapi)
|
4
|
+
[](https://travis-ci.org/zhandao/zero-rails_openapi)
|
5
|
+
[](https://codeclimate.com/github/zhandao/zero-rails_openapi/maintainability)
|
6
|
+
|
7
|
+
一套简洁的 DSL,用于为 Rails 应用生成 OpenAPI Specification 3 (**OAS3**, 旧称「Swagger3」) 标准的 JSON 文档。
|
8
|
+
(你还可以使用 Swagger-UI 3.2.0 以上版本来可视化所生成的文档。)
|
9
|
+
|
10
|
+
## Contributing
|
11
|
+
|
12
|
+
**这里是栈刀 = ▽ =
|
13
|
+
如果你在寻找能清晰书写 OAS API 文档的 DSL 工具,俺这个还挺不错的 ~
|
14
|
+
你还可以复用其所[产出](#about-openapidocs-and-openapipaths_index)来写一些扩展,比如参数自动校验什么的(我有写哦)。
|
15
|
+
有什么想法敬请 PR,谢过!
|
16
|
+
另外,走过路过不妨来个 star?**
|
17
|
+
|
18
|
+
## Table of Contents
|
19
|
+
|
20
|
+
- [关于 OAS](#about-oas) (OpenAPI Specification)
|
21
|
+
- [安装](#installation)
|
22
|
+
- [配置](#configure)
|
23
|
+
- [DSL 介绍及用例](#usage---dsl)
|
24
|
+
- [用于 `api` 和 `api_dry` 块内的 DSL(描述 API 的参数、响应等)](#dsl-methods-inside-api-and-api_drys-block)
|
25
|
+
- [用于 `components` 块内的 DSL(描述可复用的组件)](#dsl-methods-inside-componentss-block-code-source)
|
26
|
+
- [执行文档生成](#usage---generate-json-documentation-file)
|
27
|
+
- [使用 Swagger-UI 可视化所生成的文档](#usage---use-swagger-uivery-beautiful-web-page-to-show-your-documentation)
|
28
|
+
- [技巧](#tricks)
|
29
|
+
- [将 DSL 写于他处,与控制器分离](#trick1---write-the-dsl-somewhere-else)
|
30
|
+
- [全局 DRY](#trick2---global-drying)
|
31
|
+
- [基于 enum 等信息自动生成参数描述](#trick3---auto-generate-description)
|
32
|
+
- [跳过或使用 DRY 时(`api_dry`)所定义的参数](#trick4---skip-or-use-parameters-define-in-api_dry)
|
33
|
+
- [基于 DB Schema 自动生成 response 的格式](#trick5---auto-generate-indexshow-actionss-response-types-based-on-db-schema)
|
34
|
+
- [定义组合的 Schema (one_of / all_of / any_of / not)](#trick6---combined-schema-one_of--all_of--any_of--not)
|
35
|
+
- [问题集](#troubleshooting)
|
36
|
+
- [有关 `OpenApi.docs` 和 `OpenApi.paths_index`](#about-openapidocs-and-openapipaths_index)
|
37
|
+
|
38
|
+
## About OAS
|
39
|
+
|
40
|
+
有关 OAS3 的所有内容请看 [OpenAPI Specification](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md)
|
41
|
+
|
42
|
+
你也可以看这份文档做初步的了解 [swagger.io](https://swagger.io/docs/specification/basic-structure/)
|
43
|
+
|
44
|
+
**我建议你应该至少了解 OAS3 的基本结构**
|
45
|
+
比如说 component(组件)—— 这能帮助你进一步减少书写文档 DSL 的代码(如果其中有很多可复用的数据结构的话)。
|
46
|
+
|
47
|
+
## Installation
|
48
|
+
|
49
|
+
选一行添加到 Gemfile:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
gem 'zero-rails_openapi'
|
53
|
+
# or
|
54
|
+
gem 'zero-rails_openapi', github: 'zhandao/zero-rails_openapi'
|
55
|
+
```
|
56
|
+
|
57
|
+
命令行执行:
|
58
|
+
|
59
|
+
$ bundle
|
60
|
+
|
61
|
+
## Configure
|
62
|
+
|
63
|
+
新建一个 initializer, 用来配置 ZRO 并定义你的文档。
|
64
|
+
|
65
|
+
这是一个简单的示例:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
# config/initializers/open_api.rb
|
69
|
+
require 'open_api'
|
70
|
+
|
71
|
+
OpenApi::Config.tap do |c|
|
72
|
+
# [REQUIRED] The output location where .json doc file will be written to.
|
73
|
+
c.file_output_path = 'public/open_api'
|
74
|
+
|
75
|
+
c.open_api_docs = {
|
76
|
+
# 对文档 `homepage` 进行定义
|
77
|
+
homepage: {
|
78
|
+
# [REQUIRED] ZRO will scan all the descendants of root_controller, then generate their docs.
|
79
|
+
root_controller: Api::V1::BaseController,
|
80
|
+
|
81
|
+
# [REQUIRED] OAS Info Object: The section contains API information.
|
82
|
+
info: {
|
83
|
+
# [REQUIRED] The title of the application.
|
84
|
+
title: 'Homepage APIs',
|
85
|
+
# Description of the application.
|
86
|
+
description: 'API documentation of Rails Application. <br/>' \
|
87
|
+
'Optional multiline or single-line Markdown-formatted description ' \
|
88
|
+
'in [CommonMark](http://spec.commonmark.org/) or `HTML`.',
|
89
|
+
# [REQUIRED] The version of the OpenAPI document
|
90
|
+
# (which is distinct from the OAS version or the API implementation version).
|
91
|
+
version: '1.0.0'
|
92
|
+
}
|
93
|
+
}
|
94
|
+
}
|
95
|
+
end
|
96
|
+
```
|
97
|
+
|
98
|
+
除了直接使用 Hash,你还可以使用 DSL 来定义文档的基本信息:
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
# config/initializers/open_api.rb
|
102
|
+
require 'open_api'
|
103
|
+
|
104
|
+
OpenApi::Config.tap do |c|
|
105
|
+
c.instance_eval do
|
106
|
+
open_api :homepage_api, root_controller: ApiDoc
|
107
|
+
info version: '1.0.0', title: 'Homepage APIs'
|
108
|
+
end
|
109
|
+
end
|
110
|
+
```
|
111
|
+
|
112
|
+
更多更详尽的配置和文档信息定义示例: [open_api.rb](documentation/examples/open_api.rb)
|
113
|
+
所有你可以配置的项目: [config.rb](lib/open_api/config.rb)
|
114
|
+
所有你可以使用的文档信息 DSL: [config_dsl.rb](lib/open_api/config_dsl.rb)
|
115
|
+
|
116
|
+
## Usage - DSL
|
117
|
+
|
118
|
+
### 首先,`include OpenApi::DSL` 到你用来写文档的基类中,例如:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
# app/controllers/api/api_controller.rb
|
122
|
+
class ApiController < ActionController::API
|
123
|
+
include OpenApi::DSL
|
124
|
+
end
|
125
|
+
```
|
126
|
+
|
127
|
+
### DSL 使用实例
|
128
|
+
|
129
|
+
这是一个最简单的实例:
|
130
|
+
|
131
|
+
```ruby
|
132
|
+
class Api::V1::ExamplesController < Api::V1::BaseController
|
133
|
+
api :index, 'GET list' do
|
134
|
+
query :page, Integer#, desc: 'page, greater than 1', range: { ge: 1 }, dft: 1
|
135
|
+
query :rows, Integer#, desc: 'per page', range: { ge: 1 }, default: 10
|
136
|
+
end
|
137
|
+
end
|
138
|
+
```
|
139
|
+
|
140
|
+
可以查看两份更详细的实例: [goods_doc.rb](documentation/examples/goods_doc.rb), 以及
|
141
|
+
[examples_controller.rb](documentation/examples/examples_controller.rb)
|
142
|
+
|
143
|
+
### 作为类方法的 DSL ([source code](lib/open_api/dsl.rb))
|
144
|
+
|
145
|
+
#### (1) `ctrl_path` (controller path) [无需调用,当且仅当你是在控制器中写文档时]
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
# method signature
|
149
|
+
ctrl_path(path)
|
150
|
+
# usage
|
151
|
+
ctrl_path 'api/v1/examples'
|
152
|
+
```
|
153
|
+
其默认设定为 `controller_path`.
|
154
|
+
|
155
|
+
[这个技巧](#trick1---write-the-dsl-somewhere-else) 展示如何使用 `ctrl_path` 来让你将 DSL 写在他处(与控制器分离),来简化你的控制器。
|
156
|
+
|
157
|
+
#### (2) `apis_tag` [optional]
|
158
|
+
|
159
|
+
```ruby
|
160
|
+
# method signature
|
161
|
+
apis_tag(name: nil, desc: '', external_doc_url: '')
|
162
|
+
# usage
|
163
|
+
apis_tag name: 'ExampleTagName', desc: 'ExamplesController\'s APIs'
|
164
|
+
```
|
165
|
+
This method allows you to set the Tag (which is a node of [OpenApi Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#openapi-object)).
|
166
|
+
|
167
|
+
desc and external_doc_url will be output to the tags[the current tag] (tag defaults to controller_name), but are optional.
|
168
|
+
|
169
|
+
#### (3) `components` [optional]
|
170
|
+
|
171
|
+
```ruby
|
172
|
+
# method signature
|
173
|
+
components(&block)
|
174
|
+
# usage
|
175
|
+
components do
|
176
|
+
# DSL for defining components
|
177
|
+
schema :DogSchema => [ { id: Integer, name: String }, dft: { id: 1, name: 'pet' } ]
|
178
|
+
query! :UidQuery => [ :uid, String, desc: 'uid' ]
|
179
|
+
resp :BadRqResp => [ 'bad request', :json ]
|
180
|
+
end
|
181
|
+
|
182
|
+
# to use component
|
183
|
+
api :action, 'summary' do
|
184
|
+
query :doge, :DogSchema # to use a Schema component
|
185
|
+
param_ref :UidQuery # to use a Parameter component
|
186
|
+
response_ref :BadRqResp # to use a Response component
|
187
|
+
end
|
188
|
+
```
|
189
|
+
Component can be used to simplify your DSL code (by using `*_ref` methods).
|
190
|
+
|
191
|
+
Each RefObj you defined is associated with components through component key.
|
192
|
+
We suggest that component keys should be camelized symbol.
|
193
|
+
|
194
|
+
#### (4) `api_dry` [optional]
|
195
|
+
|
196
|
+
This method is for DRYing.
|
197
|
+
|
198
|
+
```ruby
|
199
|
+
# method signature
|
200
|
+
api_dry(action = :all, desc = '', &block)
|
201
|
+
# usage
|
202
|
+
api_dry :all, 'common response' # block ...
|
203
|
+
api_dry :index # block ...
|
204
|
+
api_dry [:index, :show] do
|
205
|
+
query! #...
|
206
|
+
end
|
207
|
+
```
|
208
|
+
|
209
|
+
As you think, the block will be executed to each specified API(action) **firstly**.
|
210
|
+
|
211
|
+
#### (5) `api` [required]
|
212
|
+
|
213
|
+
Define the specified API (controller action, in the following example is index).
|
214
|
+
|
215
|
+
```ruby
|
216
|
+
# method signature
|
217
|
+
api(action, summary = '', builder: nil, skip: [ ], use: [ ], &block)
|
218
|
+
# usage
|
219
|
+
api :index, '(SUMMARY) this api blah blah ...', builder: :index # block ...
|
220
|
+
```
|
221
|
+
If you pass `builder`, and `generate_jbuilder_file` is set to `true` (in your initializer),
|
222
|
+
ZRO will generate JBuilder file by using specified template called `index`.
|
223
|
+
About template settings, see: [open_api.rb](documentation/examples/open_api.rb)
|
224
|
+
|
225
|
+
`use` and `skip` options: to use or skip the parameters defined in `api_dry`.
|
226
|
+
|
227
|
+
```ruby
|
228
|
+
api :show, 'summary', use: [:id] # => it will only take :id from DRYed result.
|
229
|
+
```
|
230
|
+
|
231
|
+
### DSL methods inside [api]() and [api_dry]()'s block
|
232
|
+
|
233
|
+
[source code](lib/open_api/dsl/api_info_obj.rb)
|
234
|
+
|
235
|
+
These following methods in the block describe the specified API action: description, valid?,
|
236
|
+
parameters, request body, responses, securities, servers.
|
237
|
+
|
238
|
+
(Here corresponds to OAS [Operation Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#operationObject))
|
239
|
+
|
240
|
+
#### (1) `this_api_is_invalid!`, its aliases:
|
241
|
+
```
|
242
|
+
this_api_is_expired!
|
243
|
+
this_api_is_unused!
|
244
|
+
this_api_is_under_repair!
|
245
|
+
```
|
246
|
+
|
247
|
+
```ruby
|
248
|
+
# method signature
|
249
|
+
this_api_is_invalid!(explain = '')
|
250
|
+
# usage
|
251
|
+
this_api_is_invalid! 'this api is expired!'
|
252
|
+
```
|
253
|
+
|
254
|
+
Then `deprecated` of this API will be set to true.
|
255
|
+
|
256
|
+
#### (2) `desc`: description for the current API and its inputs (parameters and request body)
|
257
|
+
|
258
|
+
```ruby
|
259
|
+
# method signature
|
260
|
+
desc(desc, param_descs = { })
|
261
|
+
# usage
|
262
|
+
desc 'current API\'s description',
|
263
|
+
id: 'desc of the parameter :id',
|
264
|
+
email: 'desc of the parameter :email'
|
265
|
+
```
|
266
|
+
|
267
|
+
You can of course describe the input in it's DSL method (like `query! :done ...`, [this line](https://github.com/zhandao/zero-rails_openapi#-dsl-usage-example)),
|
268
|
+
but that will make it long and ugly. We recommend that unite descriptions in this place.
|
269
|
+
|
270
|
+
In addition, when you want to dry the same parameters (each with a different description), it will be of great use.
|
271
|
+
|
272
|
+
#### (3) `param` family methods (OAS - [Parameter Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#parameterObject))
|
273
|
+
|
274
|
+
Define the parameters for the API (action).
|
275
|
+
```
|
276
|
+
param
|
277
|
+
param_ref # for reuse component,
|
278
|
+
# it links sepcified RefObjs (by component keys) to current parameters.
|
279
|
+
header, path, query, cookie # will pass specified parameter location to `param`
|
280
|
+
header!, path!, query!, cookie! # bang method of above methods
|
281
|
+
do_* by: { parameter_definations } # batch definition parameters, such as do_path, do_query
|
282
|
+
order # order parameters by names array you passed
|
283
|
+
examples # define examples of parameters
|
284
|
+
```
|
285
|
+
**The bang method (which's name is end of a exclamation point `!`) means this param is required, so without `!` means optional.**
|
286
|
+
**THE SAME BELOW.**
|
287
|
+
|
288
|
+
```ruby
|
289
|
+
# `param_type` just is the location of parameter, like: query, path
|
290
|
+
# `schema_type` is the type of parameter, like: String, Integer (must be a constant)
|
291
|
+
# For more explanation, please click the link below ↓↓↓
|
292
|
+
# method signature
|
293
|
+
param(param_type, param_name, schema_type, is_required, schema_hash = { })
|
294
|
+
# usage
|
295
|
+
param :query, :page, Integer, :req, range: { gt: 0, le: 5 }, desc: 'page'
|
296
|
+
|
297
|
+
|
298
|
+
# method signature
|
299
|
+
param_ref(component_key, *component_keys) # should pass at least 1 key
|
300
|
+
# usage
|
301
|
+
param_ref :IdPath
|
302
|
+
param_ref :IdPath, :NameQuery, :TokenHeader
|
303
|
+
|
304
|
+
|
305
|
+
### method signature
|
306
|
+
header(param_name, schema_type = nil, one_of: nil, all_of: nil, any_of: nil, not: nil, **schema_hash)
|
307
|
+
header!(param_name, schema_type = nil, one_of: nil, all_of: nil, any_of: nil, not: nil, **schema_hash)
|
308
|
+
query!(param_name, schema_type = nil, one_of: nil, all_of: nil, any_of: nil, not: nil, **schema_hash)
|
309
|
+
# ...
|
310
|
+
### usage
|
311
|
+
header! 'Token', String
|
312
|
+
query! :readed, Boolean, must_be: true, default: false
|
313
|
+
# The same effect as above, but not simple
|
314
|
+
param :query, :readed, Boolean, :req, must_be: true, default: false
|
315
|
+
#
|
316
|
+
# When schema_type is a Object
|
317
|
+
# (describe by hash, key means prop's name, value means prop's schema_type)
|
318
|
+
query :good, { name: String, price: Float, spec: { size: String, weight: Integer } }, desc: 'good info'
|
319
|
+
# Or you can use `type:` to sign the schema_type, maybe this is clearer for describing object
|
320
|
+
query :good, type: { name: String, price: Float, spec: { size: String, weight: Integer } }, desc: 'good info'
|
321
|
+
#
|
322
|
+
query :good_name, type: String # It's also OK, but some superfluous
|
323
|
+
query :good_name, String # recommended
|
324
|
+
# About Combined Schema (`one_of` ..), see the link below.
|
325
|
+
|
326
|
+
|
327
|
+
# method signature
|
328
|
+
do_query(by:)
|
329
|
+
# usage
|
330
|
+
do_query by: {
|
331
|
+
search_type: String,
|
332
|
+
search_val: String,
|
333
|
+
export!: Boolean
|
334
|
+
}
|
335
|
+
# The same effect as above, but a little bit repetitive
|
336
|
+
query :search_type, String
|
337
|
+
query :search_val, String
|
338
|
+
query! :export, Boolean
|
339
|
+
|
340
|
+
|
341
|
+
# method signature
|
342
|
+
# `exp_by` (select_example_by): choose the example fields.
|
343
|
+
examples(exp_by = :all, examples_hash)
|
344
|
+
# usage
|
345
|
+
# it defines 2 examples by using parameter :id and :name
|
346
|
+
# if pass :all to `exp_by`, keys will be all the parameter's names.
|
347
|
+
examples [:id, :name], {
|
348
|
+
:right_input => [ 1, 'user'], # == { id: 1, name: 'user' }
|
349
|
+
:wrong_input => [ -1, '' ]
|
350
|
+
}
|
351
|
+
```
|
352
|
+
|
353
|
+
[This trick show you how to define combined schema (by using `one_of` ..)](#trick6---combined-schema-one-of--all-of--any-of--not)
|
354
|
+
|
355
|
+
[**>> More About `param` DSL <<**](documentation/parameter.md)
|
356
|
+
|
357
|
+
#### (4) `request_body` family methods (OAS - [Request Body Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#requestBodyObject))
|
358
|
+
|
359
|
+
OpenAPI 3.0 uses the requestBody keyword to distinguish the payload from parameters.
|
360
|
+
```
|
361
|
+
request_body
|
362
|
+
body_ref # for reuse component,
|
363
|
+
# it links sepcified RefObjs (by component keys) to current body.
|
364
|
+
body, body! # alias of request_body
|
365
|
+
form, form! # define a multipart/form-data body
|
366
|
+
file, file! # define a File media-type body
|
367
|
+
```
|
368
|
+
|
369
|
+
```ruby
|
370
|
+
# method signature
|
371
|
+
request_body(is_required, media_type, desc = '', schema_hash = { })
|
372
|
+
# usage
|
373
|
+
request_body :opt, :form, '', type: { id!: Integer, name: String }
|
374
|
+
# or
|
375
|
+
request_body :opt, :form, '', data: { id!: Integer, name: String }
|
376
|
+
|
377
|
+
|
378
|
+
# method signature
|
379
|
+
body_ref(component_key)
|
380
|
+
# usage
|
381
|
+
body_ref :UpdateDogeBody
|
382
|
+
|
383
|
+
|
384
|
+
# method signature
|
385
|
+
body!(media_type, desc = '', schema_hash = { })
|
386
|
+
# usage
|
387
|
+
body :json
|
388
|
+
|
389
|
+
|
390
|
+
# method implement
|
391
|
+
def form desc = '', schema_hash = { }
|
392
|
+
body :form, desc, schema_hash
|
393
|
+
end
|
394
|
+
# usage
|
395
|
+
form! 'register', data: {
|
396
|
+
name: String,
|
397
|
+
password: String,
|
398
|
+
password_confirmation: String
|
399
|
+
}
|
400
|
+
# advance usage
|
401
|
+
form 'for creating a user', data: {
|
402
|
+
:name! => { type: String, desc: 'user name' },
|
403
|
+
:password! => { type: String, pattern: /[0-9]{6,10}/, desc: 'password' },
|
404
|
+
# optional
|
405
|
+
:remarks => { type: String, desc: 'remarks' },
|
406
|
+
}, exp_by: %i[ name password ],
|
407
|
+
examples: { # ↓ ↓
|
408
|
+
:right_input => [ 'user1', '123456' ],
|
409
|
+
:wrong_input => [ 'user2', 'abc' ]
|
410
|
+
}
|
411
|
+
|
412
|
+
|
413
|
+
# about `file`
|
414
|
+
def file! media_type, desc = '', schema_hash = { type: File }
|
415
|
+
body! media_type, desc, schema_hash
|
416
|
+
end
|
417
|
+
```
|
418
|
+
|
419
|
+
1. **Notice:** Each API should only declare a request body
|
420
|
+
That is, all of the above methods you can only choose one of them.
|
421
|
+
(But **multiple media types** will be supported in the future).
|
422
|
+
2. `media_type`: we provide some [mapping](lib/oas_objs/media_type_obj.rb) from symbols to real media-types.
|
423
|
+
3. `schema_hash`: as above (see param).
|
424
|
+
**One thing that should be noted is: when use Hash writing, `scham_type` is writed in schema_hash using key :type.**
|
425
|
+
4. `exp_by` and `examples`: for the above example, the following has the same effect:
|
426
|
+
```
|
427
|
+
examples: {
|
428
|
+
:right_input => { name: 'user1', password: '123456' },
|
429
|
+
:wrong_input => { name: 'user2', password: 'abc' }
|
430
|
+
}
|
431
|
+
```
|
432
|
+
|
433
|
+
#### (5) `response` family methods (OAS - [Response Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#response-object))
|
434
|
+
|
435
|
+
Define the responses for the API (action).
|
436
|
+
```
|
437
|
+
response or resp
|
438
|
+
response_ref
|
439
|
+
default_response or dft_resp
|
440
|
+
error_response, other_response, oth_resp, error, err_resp # response's aliases, should be used in the error response context.
|
441
|
+
merge_to_resp
|
442
|
+
```
|
443
|
+
|
444
|
+
```ruby
|
445
|
+
# method signature
|
446
|
+
response(response_code, desc, media_type = nil, schema_hash = { })
|
447
|
+
# usage
|
448
|
+
response 200, 'query result', :pdf, type: File
|
449
|
+
|
450
|
+
# method signature
|
451
|
+
response_ref(code_compkey_hash)
|
452
|
+
# usage
|
453
|
+
response_ref 700 => :AResp, 800 => :BResp
|
454
|
+
|
455
|
+
# method signature
|
456
|
+
merge_to_resp(code, by:)
|
457
|
+
# usage
|
458
|
+
merge_to_resp 200, by: {
|
459
|
+
data: {
|
460
|
+
type: String
|
461
|
+
}
|
462
|
+
}
|
463
|
+
```
|
464
|
+
|
465
|
+
**practice:** Combined with wrong class, automatically generate error responses. [AutoGenDoc](documentation/examples/auto_gen_doc.rb#L63)
|
466
|
+
|
467
|
+
#### (6) Authentication and Authorization
|
468
|
+
|
469
|
+
First of all, please make sure that you have read one of the following documents:
|
470
|
+
[OpenApi Auth](https://swagger.io/docs/specification/authentication/)
|
471
|
+
or [securitySchemeObject](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#securitySchemeObject)
|
472
|
+
|
473
|
+
##### Define Security Scheme
|
474
|
+
|
475
|
+
Use these DSL in your initializer or `components` block:
|
476
|
+
```
|
477
|
+
security_scheme # alias `auth_scheme`
|
478
|
+
base_auth # will call `security_scheme`
|
479
|
+
bearer_auth # will call `security_scheme`
|
480
|
+
api_key # will call `security_scheme`
|
481
|
+
```
|
482
|
+
It's very simple to use (if you understand the above document)
|
483
|
+
```ruby
|
484
|
+
# method signature
|
485
|
+
security_scheme(scheme_name, other_info)
|
486
|
+
# usage
|
487
|
+
security_scheme :BasicAuth, { type: 'http', scheme: 'basic', desc: 'basic auth' }
|
488
|
+
|
489
|
+
# method signature
|
490
|
+
base_auth(scheme_name, other_info = { })
|
491
|
+
bearer_auth(scheme_name, format = 'JWT', other_info = { })
|
492
|
+
api_key(scheme_name, field:, in:, **other_info)
|
493
|
+
# usage
|
494
|
+
base_auth :BasicAuth, desc: 'basic auth' # the same effect as ↑↑↑
|
495
|
+
bearer_auth :Token
|
496
|
+
api_key :ApiKeyAuth, field: 'X-API-Key', in: 'header', desc: 'pass api key to header'
|
497
|
+
```
|
498
|
+
|
499
|
+
##### Apply Security
|
500
|
+
|
501
|
+
```
|
502
|
+
# In initializer
|
503
|
+
# Global effectiveness
|
504
|
+
global_security_require
|
505
|
+
global_security # alias
|
506
|
+
global_auth # alias
|
507
|
+
|
508
|
+
# In `api`'s block
|
509
|
+
# Only valid for the current controller
|
510
|
+
security_require
|
511
|
+
security # alias
|
512
|
+
auth # alias
|
513
|
+
need_auth # alias
|
514
|
+
```
|
515
|
+
Name is different, signature and usage is similar.
|
516
|
+
```ruby
|
517
|
+
# method signature
|
518
|
+
security_require(scheme_name, scopes: [ ])
|
519
|
+
# usage
|
520
|
+
global_auth :Token
|
521
|
+
need_auth :Token
|
522
|
+
auth :OAuth, scopes: %w[ read_example admin ]
|
523
|
+
```
|
524
|
+
|
525
|
+
#### (7) Overriding Global Servers by `server`
|
526
|
+
|
527
|
+
```ruby
|
528
|
+
# method signature
|
529
|
+
server(url, desc)
|
530
|
+
# usage
|
531
|
+
server 'http://localhost:3000', 'local'
|
532
|
+
```
|
533
|
+
|
534
|
+
### DSL methods inside [components]()'s block ([code source](lib/open_api/dsl/components.rb))
|
535
|
+
|
536
|
+
(Here corresponds to OAS [Components Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#componentsObject))
|
537
|
+
|
538
|
+
Inside `components`'s block,
|
539
|
+
you can use the same DSL as [[DSL methods inside `api` and `api_dry`'s block]](#dsl-methods-inside-api-and-api_drys-block).
|
540
|
+
But there are two differences:
|
541
|
+
|
542
|
+
(1) Each method needs to pass one more parameter `component_key`
|
543
|
+
(in the first parameter position),
|
544
|
+
this will be used as the reference name for the component.
|
545
|
+
|
546
|
+
```ruby
|
547
|
+
query! :UidQuery, :uid, String
|
548
|
+
```
|
549
|
+
This writing is feasible but not recommended,
|
550
|
+
because component's key and parameter's name seem easy to confuse.
|
551
|
+
The recommended writing is:
|
552
|
+
|
553
|
+
```ruby
|
554
|
+
query! :UidQuery => [:uid, String]
|
555
|
+
```
|
556
|
+
|
557
|
+
(2) You can use `schema` to define a Schema Component.
|
558
|
+
|
559
|
+
```ruby
|
560
|
+
# method signature
|
561
|
+
schema(component_key, type = nil, one_of: nil, all_of: nil, any_of: nil, not: nil, **schema_hash)
|
562
|
+
# usage
|
563
|
+
schema :Dog => [ String, desc: 'dogee' ] # <= schema_type is `String`
|
564
|
+
# advance usage
|
565
|
+
schema :Dog => [
|
566
|
+
{
|
567
|
+
id!: Integer,
|
568
|
+
name: { type: String, must_be: 'name', desc: 'name' }
|
569
|
+
}, # <= this hash is schema type[1]
|
570
|
+
dft: { id: 1, name: 'pet' },
|
571
|
+
desc: 'dogee'
|
572
|
+
]
|
573
|
+
# or (unrecommended)
|
574
|
+
schema :Dog, { id!: Integer, name: String }, dft: { id: 1, name: 'pet' }, desc: 'dogee'
|
575
|
+
#
|
576
|
+
# pass a ActiveRecord class constant as `component_key`,
|
577
|
+
# it will automatically read the db schema to generate the component.
|
578
|
+
schema User # easy! And the component_key will be :User
|
579
|
+
```
|
580
|
+
[1] see: [Type](documentation/parameter.md#type-schema_type)
|
581
|
+
|
582
|
+
## Usage - Generate JSON Documentation File
|
583
|
+
|
584
|
+
Use `OpenApi.write_docs`:
|
585
|
+
|
586
|
+
```ruby
|
587
|
+
# initializer
|
588
|
+
OpenApi.write_docs generate_files: !Rails.env.production?
|
589
|
+
|
590
|
+
# or run directly in console
|
591
|
+
OpenApi.write_docs # will generate json doc files
|
592
|
+
```
|
593
|
+
|
594
|
+
Then the JSON files will be written to the directories you set. (Each API a file.)
|
595
|
+
|
596
|
+
## Usage - Use Swagger UI(very beautiful web page) to show your Documentation
|
597
|
+
|
598
|
+
Download [Swagger UI](https://github.com/swagger-api/swagger-ui) (version >= 2.3.0 support the OAS3)
|
599
|
+
to your project,
|
600
|
+
change the default JSON file path(url) in index.html.
|
601
|
+
In order to use it, you may have to enable CORS, [see](https://github.com/swagger-api/swagger-ui#cors-support)
|
602
|
+
|
603
|
+
## Tricks
|
604
|
+
|
605
|
+
### Trick1 - Write the DSL Somewhere Else
|
606
|
+
|
607
|
+
Does your documentation take too many lines?
|
608
|
+
Do you want to separate documentation from business controller to simplify both?
|
609
|
+
Very easy! Just follow
|
610
|
+
|
611
|
+
```ruby
|
612
|
+
# config/initializers/open_api.rb
|
613
|
+
# in your configuration
|
614
|
+
root_controller: ApiDoc
|
615
|
+
|
616
|
+
# app/api_doc/api_doc.rb
|
617
|
+
require 'open_api/dsl'
|
618
|
+
|
619
|
+
class ApiDoc < Object
|
620
|
+
include OpenApi::DSL
|
621
|
+
end
|
622
|
+
|
623
|
+
# app/api_doc/v1/examples_doc.rb
|
624
|
+
class V1::ExamplesDoc < ApiDoc
|
625
|
+
ctrl_path 'api/v1/examples'
|
626
|
+
|
627
|
+
api :index do
|
628
|
+
# ...
|
629
|
+
end
|
630
|
+
end
|
631
|
+
```
|
632
|
+
|
633
|
+
Notes: file name ends in `_doc.rb` by default, but you can change via `Config.doc_location`
|
634
|
+
(it should be file paths, defaults to `./app/**/*_doc.rb`).
|
635
|
+
|
636
|
+
### Trick2 - Global DRYing
|
637
|
+
|
638
|
+
Method `api_dry` is for DRY but its scope is limited to the current controller.
|
639
|
+
|
640
|
+
I have no idea of best practices, But you can look at this [file](documentation/examples/auto_gen_doc.rb).
|
641
|
+
The implementation of the file is: do `api_dry` when inherits the base controller inside `inherited` method.
|
642
|
+
|
643
|
+
You can use `sort` to specify the order of parameters.
|
644
|
+
|
645
|
+
### Trick3 - Auto Generate Description
|
646
|
+
|
647
|
+
```ruby
|
648
|
+
desc 'api desc',
|
649
|
+
search_type!: 'search field, allows:<br/>'
|
650
|
+
query :search_type, String, enum: %w[name creator category price]
|
651
|
+
|
652
|
+
# or
|
653
|
+
|
654
|
+
query :search_type, String, desc!: 'search field, allows:<br/>',
|
655
|
+
enum: %w[name creator category price]
|
656
|
+
```
|
657
|
+
|
658
|
+
Notice `!` use (`search_type!`, `desc!`), it tells ZRO to append
|
659
|
+
information that analyzed from definitions (enum, must_be ..) to description automatically.
|
660
|
+
|
661
|
+
Any one of above will generate:
|
662
|
+
> search field, allows:<br/>1/ name<br/>2/ creator,<br/>3/ category<br/>4/ price<br/>
|
663
|
+
|
664
|
+
You can also use Hash to define `enum`:
|
665
|
+
```ruby
|
666
|
+
query :view, String, desc: 'allows values<br/>', enum: {
|
667
|
+
'all goods (default)': :all,
|
668
|
+
'only online': :online,
|
669
|
+
'only offline': :offline,
|
670
|
+
'expensive goods': :get,
|
671
|
+
'cheap goods': :borrow,
|
672
|
+
}
|
673
|
+
```
|
674
|
+
Read this [file](documentation/examples/auto_gen_desc.rb) to learn more.
|
675
|
+
|
676
|
+
### Trick4 - Skip or Use parameters define in api_dry
|
677
|
+
|
678
|
+
Pass `skip: []` and `use: []` to `api` like following code:
|
679
|
+
```ruby
|
680
|
+
api :index, 'desc', builder: :index, skip: [ :Token ]
|
681
|
+
```
|
682
|
+
|
683
|
+
Look at this [file](documentation/examples/goods_doc.rb) to learn more.
|
684
|
+
|
685
|
+
### Trick5 - Auto Generate index/show Actions's Response-Types Based on DB Schema
|
686
|
+
|
687
|
+
Use method `load_schema` in `api_dry`.
|
688
|
+
|
689
|
+
See this [file](documentation/examples/auto_gen_doc.rb#L51) for uasge information.
|
690
|
+
|
691
|
+
### Trick6 - Combined Schema (one_of / all_of / any_of / not)
|
692
|
+
|
693
|
+
```ruby
|
694
|
+
query :combination, one_of: [ :GoodSchema, String, { type: Integer, desc: 'integer input'}]
|
695
|
+
|
696
|
+
form '', data: {
|
697
|
+
:combination_in_form => { any_of: [ Integer, String ] }
|
698
|
+
}
|
699
|
+
|
700
|
+
schema :PetSchema => [ not: [ Integer, Boolean ] ]
|
701
|
+
```
|
702
|
+
|
703
|
+
OAS: [link1](https://swagger.io/docs/specification/data-models/oneof-anyof-allof-not/),
|
704
|
+
[link2](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaObject)
|
705
|
+
|
706
|
+
## Troubleshooting
|
707
|
+
|
708
|
+
- **You wrote document of the current API, but not find in the generated json file?**
|
709
|
+
Check your routing settings.
|
710
|
+
- **Undefine method `match?`**
|
711
|
+
Monkey patches for `String` and `Symbol`:
|
712
|
+
```ruby
|
713
|
+
class String # Symbol
|
714
|
+
def match?(pattern); !match(pattern).nil? end
|
715
|
+
end
|
716
|
+
```
|
717
|
+
- **Report error when require `routes.rb`?***
|
718
|
+
1. Run `rails routes`.
|
719
|
+
2. Copy the output to a file, for example `config/routes.txt`.
|
720
|
+
Ignore the file `config/routes.txt`.
|
721
|
+
3. Put `c.rails_routes_file = 'config/routes.txt'` to your ZRO config.
|
722
|
+
|
723
|
+
|
724
|
+
## About `OpenApi.docs` and `OpenApi.paths_index`
|
725
|
+
|
726
|
+
After `OpenApi.write_docs`, the above two module variables will be generated.
|
727
|
+
|
728
|
+
`OpenApi.docs`: A Hash with API names as keys, and documents of each APIs as values.
|
729
|
+
documents are instances of ActiveSupport::HashWithIndifferentAccess.
|
730
|
+
|
731
|
+
`OpenApi.paths_index`: Inverted index of controller path to API name mappings.
|
732
|
+
Like: `{ 'api/v1/examples' => :homepage_api }`
|
733
|
+
It's useful when you want to look up a document based on a controller and do something.
|
734
|
+
|
735
|
+
## Development
|
736
|
+
|
737
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
738
|
+
|
739
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
740
|
+
|
741
|
+
## License
|
742
|
+
|
743
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
744
|
+
|
745
|
+
## Code of Conduct
|
746
|
+
|
747
|
+
Everyone interacting in the Zero-OpenApi project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](CODE_OF_CONDUCT.md).
|