zero-rails_openapi 1.4.0 → 1.4.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem Version](https://badge.fury.io/rb/zero-rails_openapi.svg)](https://badge.fury.io/rb/zero-rails_openapi)
|
4
4
|
[![Build Status](https://travis-ci.org/zhandao/zero-rails_openapi.svg?branch=master)](https://travis-ci.org/zhandao/zero-rails_openapi)
|
5
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/471fd60f6eb7b019ceed/maintainability)](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
|
+
[![Gem Version](https://badge.fury.io/rb/zero-rails_openapi.svg)](https://badge.fury.io/rb/zero-rails_openapi)
|
4
|
+
[![Build Status](https://travis-ci.org/zhandao/zero-rails_openapi.svg?branch=master)](https://travis-ci.org/zhandao/zero-rails_openapi)
|
5
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/471fd60f6eb7b019ceed/maintainability)](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).
|