zero-rails_openapi 1.5.2 → 1.5.3
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 +16 -0
- data/Gemfile.lock +5 -3
- data/README.md +149 -149
- data/README_zh.md +183 -167
- data/documentation/examples/examples_controller.rb +1 -1
- data/documentation/parameter.md +3 -3
- data/lib/oas_objs/param_obj.rb +7 -18
- data/lib/oas_objs/ref_obj.rb +2 -1
- data/lib/oas_objs/schema_obj.rb +26 -62
- data/lib/oas_objs/schema_obj_helpers.rb +37 -21
- data/lib/open_api/dsl/api_info.rb +24 -41
- data/lib/open_api/dsl/common_dsl.rb +3 -2
- data/lib/open_api/dsl/components.rb +25 -33
- data/lib/open_api/dsl/helpers.rb +24 -8
- data/lib/open_api/dsl.rb +3 -2
- data/lib/open_api/generator.rb +7 -7
- data/lib/open_api/version.rb +1 -1
- data/zero-rails_openapi.gemspec +3 -0
- metadata +16 -2
data/README.md
CHANGED
@@ -5,8 +5,9 @@
|
|
5
5
|
[](https://codeclimate.com/github/zhandao/zero-rails_openapi/maintainability)
|
6
6
|
[](https://codeclimate.com/github/zhandao/zero-rails_openapi/test_coverage)
|
7
7
|
[](https://gitter.im/zero-rails_openapi/Lobby)
|
8
|
-
|
9
|
-
|
8
|
+
[](https://www.codetriage.com/zhandao/zero-rails_openapi)
|
9
|
+
|
10
|
+
Concise DSL for generating OpenAPI Specification 3 (**OAS3**, formerly Swagger3) JSON documentation for Rails application,
|
10
11
|
then you can use Swagger UI 3.2.0+ to show the documentation.
|
11
12
|
|
12
13
|
## Contributing
|
@@ -14,7 +15,7 @@
|
|
14
15
|
**Hi, here is ZhanDao = ▽ =
|
15
16
|
I think it's a very useful tool when you want to write API document clearly.
|
16
17
|
I'm looking forward to your issue and PR, thanks!**
|
17
|
-
|
18
|
+
|
18
19
|
And, if you have any questions, please read the test code first.
|
19
20
|
such as [api DSL](spec/api_info_obj_spec.rb) and [schema Obj](spec/oas_objs/schema_obj_spec.rb).
|
20
21
|
|
@@ -24,6 +25,7 @@
|
|
24
25
|
- [Installation](#installation)
|
25
26
|
- [Configure](#configure)
|
26
27
|
- [Usage - DSL](#usage---dsl)
|
28
|
+
- [Basic DSL](#basic-dsl)
|
27
29
|
- [DSL methods inside `api` and `api_dry`'s block](#dsl-methods-inside-api-and-api_drys-block)
|
28
30
|
- [DSL methods inside `components`'s block](#dsl-methods-inside-componentss-block-code-source)
|
29
31
|
- [Run! - Generate JSON documentation file](#run---generate-json-documentation-file)
|
@@ -41,51 +43,51 @@
|
|
41
43
|
## About OAS
|
42
44
|
|
43
45
|
Everything about OAS3 is on [OpenAPI Specification](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md)
|
44
|
-
|
46
|
+
|
45
47
|
You can getting started from [swagger.io](https://swagger.io/docs/specification/basic-structure/)
|
46
|
-
|
48
|
+
|
47
49
|
**I suggest you should understand OAS3's basic structure at least.**
|
48
|
-
such as component (can help you reuse DSL code, when your apis are used with the
|
50
|
+
such as component (can help you reuse DSL code, when your apis are used with the
|
49
51
|
same data structure).
|
50
52
|
|
51
53
|
## Installation
|
52
54
|
|
53
55
|
Add this line to your Rails's Gemfile:
|
54
|
-
|
56
|
+
|
55
57
|
```ruby
|
56
58
|
gem 'zero-rails_openapi'
|
57
59
|
# or
|
58
60
|
gem 'zero-rails_openapi', github: 'zhandao/zero-rails_openapi'
|
59
61
|
```
|
60
|
-
|
62
|
+
|
61
63
|
And then execute:
|
62
|
-
|
64
|
+
|
63
65
|
$ bundle
|
64
|
-
|
66
|
+
|
65
67
|
Or install it yourself as:
|
66
|
-
|
68
|
+
|
67
69
|
$ gem install zero-rails_openapi
|
68
|
-
|
70
|
+
|
69
71
|
## Configure
|
70
72
|
|
71
73
|
Create an initializer, configure ZRO and define your OpenApi documents.
|
72
|
-
|
74
|
+
|
73
75
|
This is the simplest example:
|
74
|
-
|
76
|
+
|
75
77
|
```ruby
|
76
78
|
# config/initializers/open_api.rb
|
77
79
|
require 'open_api'
|
78
|
-
|
80
|
+
|
79
81
|
OpenApi::Config.tap do |c|
|
80
82
|
# [REQUIRED] The output location where .json doc file will be written to.
|
81
83
|
c.file_output_path = 'public/open_api'
|
82
|
-
|
84
|
+
|
83
85
|
c.open_api_docs = {
|
84
86
|
# The definition of the document `homepage`.
|
85
87
|
homepage: {
|
86
88
|
# [REQUIRED] ZRO will scan all the descendants of base_doc_class, then generate their docs.
|
87
89
|
base_doc_class: Api::V1::BaseController,
|
88
|
-
|
90
|
+
|
89
91
|
# [REQUIRED] OAS Info Object: The section contains API information.
|
90
92
|
info: {
|
91
93
|
# [REQUIRED] The title of the application.
|
@@ -102,14 +104,14 @@
|
|
102
104
|
}
|
103
105
|
end
|
104
106
|
```
|
105
|
-
|
107
|
+
|
106
108
|
In addition to directly using Hash,
|
107
109
|
you can also use DSL to define the document information:
|
108
|
-
|
110
|
+
|
109
111
|
```ruby
|
110
112
|
# config/initializers/open_api.rb
|
111
113
|
require 'open_api'
|
112
|
-
|
114
|
+
|
113
115
|
OpenApi::Config.tap do |c|
|
114
116
|
c.instance_eval do
|
115
117
|
open_api :homepage_api, base_doc_class: ApiDoc
|
@@ -117,7 +119,7 @@
|
|
117
119
|
end
|
118
120
|
end
|
119
121
|
```
|
120
|
-
|
122
|
+
|
121
123
|
For more detailed configuration: [open_api.rb](documentation/examples/open_api.rb)
|
122
124
|
See all the settings you can configure: [config.rb](lib/open_api/config.rb)
|
123
125
|
See all the Document Definition DSL: [config_dsl.rb](lib/open_api/config_dsl.rb)
|
@@ -136,7 +138,7 @@
|
|
136
138
|
### DSL Usage Example
|
137
139
|
|
138
140
|
Here is the simplest usage:
|
139
|
-
|
141
|
+
|
140
142
|
```ruby
|
141
143
|
class Api::ExamplesController < ApiController
|
142
144
|
api :index, 'GET list' do
|
@@ -145,11 +147,11 @@
|
|
145
147
|
end
|
146
148
|
end
|
147
149
|
```
|
148
|
-
|
150
|
+
|
149
151
|
For more example, see [goods_doc.rb](documentation/examples/goods_doc.rb), and
|
150
152
|
[examples_controller.rb](documentation/examples/examples_controller.rb)
|
151
153
|
|
152
|
-
### DSL
|
154
|
+
### Basic DSL ([source code](lib/open_api/dsl.rb))
|
153
155
|
|
154
156
|
#### (1) `route_base` [optional if you're writing DSL in controller]
|
155
157
|
|
@@ -160,9 +162,9 @@
|
|
160
162
|
route_base 'api/v1/examples'
|
161
163
|
```
|
162
164
|
It is optional because `route_base` defaults to `controller_path`.
|
163
|
-
|
164
|
-
[Here's a trick](#trick1---write-the-dsl-somewhere-else): Using `route_base`, you can write the DSL somewhere else
|
165
|
-
to simplify the current controller.
|
165
|
+
|
166
|
+
[Here's a trick](#trick1---write-the-dsl-somewhere-else): Using `route_base`, you can write the DSL somewhere else
|
167
|
+
to simplify the current controller.
|
166
168
|
|
167
169
|
#### (2) `doc_tag` [optional]
|
168
170
|
|
@@ -170,11 +172,11 @@
|
|
170
172
|
# method signature
|
171
173
|
doc_tag(name: nil, desc: '', external_doc_url: nil)
|
172
174
|
# usage
|
173
|
-
doc_tag name: 'ExampleTagName', desc:
|
175
|
+
doc_tag name: 'ExampleTagName', desc: "ExamplesController's APIs"
|
174
176
|
```
|
175
|
-
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)).
|
176
|
-
|
177
|
-
|
177
|
+
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)).
|
178
|
+
|
179
|
+
Tag's name defaults to controller_name. desc and external_doc_url are optional.
|
178
180
|
|
179
181
|
#### (3) `components` [optional]
|
180
182
|
|
@@ -188,7 +190,7 @@
|
|
188
190
|
query! :UidQuery => [ :uid, String, desc: 'uid' ]
|
189
191
|
resp :BadRqResp => [ 'bad request', :json ]
|
190
192
|
end
|
191
|
-
|
193
|
+
|
192
194
|
# to use component
|
193
195
|
api :action, 'summary' do
|
194
196
|
query :doge, :DogSchema # to use a Schema component
|
@@ -196,15 +198,16 @@
|
|
196
198
|
response_ref :BadRqResp # to use a Response component
|
197
199
|
end
|
198
200
|
```
|
199
|
-
Component can be used to simplify your DSL code
|
200
|
-
|
201
|
-
|
202
|
-
|
201
|
+
Component can be used to simplify your DSL code
|
202
|
+
(that is, to refer to the defined Component object by `*_ref` methods).
|
203
|
+
|
204
|
+
Each RefObj is associated with components through component key.
|
205
|
+
We suggest that component keys should be camelized, and must be Symbol.
|
203
206
|
|
204
207
|
#### (4) `api_dry` [optional]
|
205
208
|
|
206
209
|
This method is for DRYing.
|
207
|
-
|
210
|
+
|
208
211
|
```ruby
|
209
212
|
# method signature
|
210
213
|
api_dry(action = :all, desc = '', &block)
|
@@ -215,37 +218,34 @@
|
|
215
218
|
query! #...
|
216
219
|
end
|
217
220
|
```
|
218
|
-
|
221
|
+
|
219
222
|
As you think, the block will be executed to each specified API(action) **firstly**.
|
220
|
-
|
223
|
+
|
221
224
|
#### (5) `api` [required]
|
222
225
|
|
223
|
-
Define the specified API
|
224
|
-
|
226
|
+
Define the specified API
|
227
|
+
(or we could say controller action).
|
228
|
+
|
225
229
|
```ruby
|
226
230
|
# method signature
|
227
|
-
api(action, summary = '', skip: [ ], use: [ ], &block)
|
231
|
+
api(action, summary = '', http: nil, skip: [ ], use: [ ], &block)
|
228
232
|
# usage
|
229
233
|
api :index, '(SUMMARY) this api blah blah ...', # block ...
|
230
234
|
```
|
231
|
-
|
235
|
+
|
232
236
|
`use` and `skip` options: to use or skip the parameters defined in `api_dry`.
|
233
|
-
|
234
|
-
[Note] JBuilder file automatic generator has been removed,
|
235
|
-
If you need this function, please refer to [here](https://github.com/zhandao/zero-rails/tree/master/lib/generators/jubilder/dsl.rb)
|
236
|
-
to implement a lib.
|
237
|
-
|
237
|
+
|
238
238
|
```ruby
|
239
|
-
api :show, 'summary', use: [:id] #
|
239
|
+
api :show, 'summary', use: [:id] # it will only take :id from DRYed result to define the API :show
|
240
240
|
```
|
241
241
|
|
242
242
|
### DSL methods inside [api]() and [api_dry]()'s block
|
243
243
|
|
244
244
|
[source code](lib/open_api/dsl/api_info_obj.rb)
|
245
|
-
|
245
|
+
|
246
246
|
These following methods in the block describe the specified API action: description, valid?,
|
247
247
|
parameters, request body, responses, securities, servers.
|
248
|
-
|
248
|
+
|
249
249
|
(Here corresponds to OAS [Operation Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#operationObject))
|
250
250
|
|
251
251
|
#### (1) `this_api_is_invalid!`, its aliases:
|
@@ -261,7 +261,7 @@
|
|
261
261
|
# usage
|
262
262
|
this_api_is_invalid! 'this api is expired!'
|
263
263
|
```
|
264
|
-
|
264
|
+
|
265
265
|
Then `deprecated` of this API will be set to true.
|
266
266
|
|
267
267
|
#### (2) `desc`: description for the current API and its inputs (parameters and request body)
|
@@ -275,9 +275,9 @@
|
|
275
275
|
email: 'desc of the parameter :email'
|
276
276
|
```
|
277
277
|
|
278
|
-
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)),
|
278
|
+
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)),
|
279
279
|
but that will make it long and ugly. We recommend that unite descriptions in this place.
|
280
|
-
|
280
|
+
|
281
281
|
In addition, when you want to dry the same parameters (each with a different description), it will be of great use.
|
282
282
|
|
283
283
|
#### (3) `param` family methods (OAS - [Parameter Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#parameterObject))
|
@@ -285,7 +285,7 @@
|
|
285
285
|
Define the parameters for the API (action).
|
286
286
|
```
|
287
287
|
param
|
288
|
-
param_ref # for reuse component,
|
288
|
+
param_ref # for reuse component,
|
289
289
|
# it links sepcified RefObjs (by component keys) to current parameters.
|
290
290
|
header, path, query, cookie # will pass specified parameter location to `param`
|
291
291
|
header!, path!, query!, cookie! # bang method of above methods
|
@@ -301,22 +301,22 @@
|
|
301
301
|
# `schema_type` is the type of parameter, like: String, Integer (must be a constant)
|
302
302
|
# For more explanation, please click the link below ↓↓↓
|
303
303
|
# method signature
|
304
|
-
param(param_type, param_name, schema_type, is_required,
|
304
|
+
param(param_type, param_name, schema_type, is_required, schema_info = { })
|
305
305
|
# usage
|
306
306
|
param :query, :page, Integer, :req, range: { gt: 0, le: 5 }, desc: 'page'
|
307
|
-
|
308
|
-
|
307
|
+
|
308
|
+
|
309
309
|
# method signature
|
310
310
|
param_ref(component_key, *component_keys) # should pass at least 1 key
|
311
311
|
# usage
|
312
312
|
param_ref :IdPath
|
313
313
|
param_ref :IdPath, :NameQuery, :TokenHeader
|
314
|
-
|
315
|
-
|
314
|
+
|
315
|
+
|
316
316
|
### method signature
|
317
|
-
header(param_name, schema_type = nil,
|
318
|
-
header!(param_name, schema_type = nil,
|
319
|
-
query!(param_name, schema_type = nil,
|
317
|
+
header(param_name, schema_type = nil, **schema_info)
|
318
|
+
header!(param_name, schema_type = nil, **schema_info)
|
319
|
+
query!(param_name, schema_type = nil, **schema_info)
|
320
320
|
# ...
|
321
321
|
### usage
|
322
322
|
header! 'Token', String
|
@@ -324,7 +324,7 @@
|
|
324
324
|
# The same effect as above, but not simple
|
325
325
|
param :query, :readed, Boolean, :req, must_be: true, default: false
|
326
326
|
#
|
327
|
-
# When schema_type is a Object
|
327
|
+
# When schema_type is a Object
|
328
328
|
# (describe by hash, key means prop's name, value means prop's schema_type)
|
329
329
|
query :good, { name: String, price: Float, spec: { size: String, weight: Integer } }, desc: 'good info'
|
330
330
|
# Or you can use `type:` to sign the schema_type, maybe this is clearer for describing object
|
@@ -347,8 +347,8 @@
|
|
347
347
|
query :search_type, String
|
348
348
|
query :search_val, String
|
349
349
|
query! :export, Boolean
|
350
|
-
|
351
|
-
|
350
|
+
|
351
|
+
|
352
352
|
# method signature
|
353
353
|
# `exp_by` (select_example_by): choose the example fields.
|
354
354
|
examples(exp_by = :all, examples_hash)
|
@@ -356,11 +356,11 @@
|
|
356
356
|
# it defines 2 examples by using parameter :id and :name
|
357
357
|
# if pass :all to `exp_by`, keys will be all the parameter's names.
|
358
358
|
examples [:id, :name], {
|
359
|
-
|
360
|
-
|
359
|
+
:right_input => [ 1, 'user'], # == { id: 1, name: 'user' }
|
360
|
+
:wrong_input => [ -1, '' ]
|
361
361
|
}
|
362
362
|
```
|
363
|
-
|
363
|
+
|
364
364
|
[This trick show you how to define combined schema (by using `one_of` ..)](#trick6---combined-schema-one-of--all-of--any-of--not)
|
365
365
|
|
366
366
|
[**>> More About `param` DSL <<**](documentation/parameter.md)
|
@@ -370,7 +370,7 @@
|
|
370
370
|
OpenAPI 3.0 uses the requestBody keyword to distinguish the payload from parameters.
|
371
371
|
```
|
372
372
|
request_body
|
373
|
-
body_ref # for reuse component,
|
373
|
+
body_ref # for reuse component,
|
374
374
|
# it links sepcified RefObjs (by component keys) to current body.
|
375
375
|
body, body! # alias of request_body
|
376
376
|
form, form! # define a multipart/form-data body
|
@@ -398,36 +398,36 @@
|
|
398
398
|
body!(media_type, data: { }, **options)
|
399
399
|
# usage
|
400
400
|
body :json
|
401
|
-
|
402
|
-
|
401
|
+
|
402
|
+
|
403
403
|
# method implement
|
404
404
|
def form data:, **options
|
405
405
|
body :form, data: data, **options
|
406
406
|
end
|
407
407
|
# usage
|
408
408
|
form! data: {
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
409
|
+
name: String,
|
410
|
+
password: String,
|
411
|
+
password_confirmation: String
|
412
|
+
}
|
413
413
|
# advance usage
|
414
414
|
form data: {
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
415
|
+
:name! => { type: String, desc: 'user name' },
|
416
|
+
:password! => { type: String, pattern: /[0-9]{6,10}/, desc: 'password' },
|
417
|
+
# optional
|
418
|
+
:remarks => { type: String, desc: 'remarks' },
|
419
|
+
}, exp_by: %i[ name password ],
|
420
|
+
examples: { # ↓ ↓
|
421
|
+
:right_input => [ 'user1', '123456' ],
|
422
|
+
:wrong_input => [ 'user2', 'abc' ]
|
423
|
+
},
|
424
|
+
desc: 'for creating a user'
|
425
|
+
|
426
|
+
|
427
427
|
# method implement
|
428
|
-
def data name, type = nil,
|
429
|
-
|
430
|
-
form data: { name =>
|
428
|
+
def data name, type = nil, schema_info = { }
|
429
|
+
schema_info[:type] = type if type.present?
|
430
|
+
form data: { name => schema_info }
|
431
431
|
end
|
432
432
|
# usage: please look at the 4th point below
|
433
433
|
|
@@ -436,9 +436,9 @@
|
|
436
436
|
body! media_type, data: data, **options
|
437
437
|
end
|
438
438
|
```
|
439
|
-
|
440
|
-
1. `media_type`: we provide some [mapping](lib/oas_objs/media_type_obj.rb) from symbols to real media-types.
|
441
|
-
2. `
|
439
|
+
|
440
|
+
1. `media_type`: we provide some [mapping](lib/oas_objs/media_type_obj.rb) from symbols to real media-types.
|
441
|
+
2. `schema_info`: as above (see param).
|
442
442
|
3. `exp_by` and `examples`: for the above example, the following has the same effect:
|
443
443
|
```
|
444
444
|
examples: {
|
@@ -459,23 +459,23 @@
|
|
459
459
|
data :param_a!, String
|
460
460
|
data :param_b, Integer
|
461
461
|
# or same as:
|
462
|
-
form
|
463
|
-
form
|
462
|
+
form data: { :param_a! => String }
|
463
|
+
form data: { :param_b => Integer }
|
464
464
|
# will generate: { "param_a": { "type": "string" }, "param_b": { "type": "integer" } } (call it X)
|
465
465
|
# therefore:
|
466
|
-
# "content": { "multipart/form-data":
|
467
|
-
# { "schema": { "type": "object", "properties": { X }, "required": [ "param_a" ] }
|
466
|
+
# "content": { "multipart/form-data":
|
467
|
+
# { "schema": { "type": "object", "properties": { X }, "required": [ "param_a" ] }
|
468
468
|
# }
|
469
469
|
```
|
470
|
-
|
470
|
+
|
471
471
|
#### (5) `response` family methods (OAS - [Response Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#response-object))
|
472
|
-
|
472
|
+
|
473
473
|
Define the responses for the API (action).
|
474
474
|
```
|
475
475
|
response # aliases: `resp` and `error`
|
476
476
|
response_ref
|
477
477
|
```
|
478
|
-
|
478
|
+
|
479
479
|
```ruby
|
480
480
|
# method signature
|
481
481
|
response(code, desc, media_type = nil, data: { }, type: nil)
|
@@ -490,17 +490,17 @@
|
|
490
490
|
# usage
|
491
491
|
response_ref 700 => :AResp, 800 => :BResp
|
492
492
|
```
|
493
|
-
|
494
|
-
**practice:** Automatically generate responses based on the agreed error class. [AutoGenDoc](documentation/examples/auto_gen_doc.rb#L63)
|
495
|
-
|
493
|
+
|
494
|
+
**practice:** Automatically generate responses based on the agreed error class. [AutoGenDoc](documentation/examples/auto_gen_doc.rb#L63)
|
495
|
+
|
496
496
|
#### (6) Authentication and Authorization
|
497
|
-
|
498
|
-
First of all, please make sure that you have read one of the following documents:
|
499
|
-
[OpenApi Auth](https://swagger.io/docs/specification/authentication/)
|
497
|
+
|
498
|
+
First of all, please make sure that you have read one of the following documents:
|
499
|
+
[OpenApi Auth](https://swagger.io/docs/specification/authentication/)
|
500
500
|
or [securitySchemeObject](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#securitySchemeObject)
|
501
|
-
|
501
|
+
|
502
502
|
##### Define Security Scheme
|
503
|
-
|
503
|
+
|
504
504
|
Use these DSL in your initializer or `components` block:
|
505
505
|
```
|
506
506
|
security_scheme # alias `auth_scheme`
|
@@ -514,7 +514,7 @@
|
|
514
514
|
security_scheme(scheme_name, other_info)
|
515
515
|
# usage
|
516
516
|
security_scheme :BasicAuth, { type: 'http', scheme: 'basic', desc: 'basic auth' }
|
517
|
-
|
517
|
+
|
518
518
|
# method signature
|
519
519
|
base_auth(scheme_name, other_info = { })
|
520
520
|
bearer_auth(scheme_name, format = 'JWT', other_info = { })
|
@@ -524,16 +524,16 @@
|
|
524
524
|
bearer_auth :Token
|
525
525
|
api_key :ApiKeyAuth, field: 'X-API-Key', in: 'header', desc: 'pass api key to header'
|
526
526
|
```
|
527
|
-
|
527
|
+
|
528
528
|
##### Apply Security
|
529
|
-
|
529
|
+
|
530
530
|
```
|
531
531
|
# In initializer
|
532
532
|
# Global effectiveness
|
533
533
|
global_security_require
|
534
534
|
global_security # alias
|
535
535
|
global_auth # alias
|
536
|
-
|
536
|
+
|
537
537
|
# In `api`'s block
|
538
538
|
# Only valid for the current controller
|
539
539
|
security_require
|
@@ -552,21 +552,21 @@
|
|
552
552
|
```
|
553
553
|
|
554
554
|
#### (7) Overriding Global Servers by `server`
|
555
|
-
|
555
|
+
|
556
556
|
```ruby
|
557
557
|
# method signature
|
558
558
|
server(url, desc: '')
|
559
559
|
# usage
|
560
560
|
server 'http://localhost:3000', desc: 'local'
|
561
561
|
```
|
562
|
-
|
562
|
+
|
563
563
|
### DSL methods inside [components]()'s block ([code source](lib/open_api/dsl/components.rb))
|
564
564
|
|
565
565
|
(Here corresponds to OAS [Components Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#componentsObject))
|
566
566
|
|
567
567
|
Inside `components`'s block,
|
568
568
|
you can use the same DSL as [[DSL methods inside `api` and `api_dry`'s block]](#dsl-methods-inside-api-and-api_drys-block).
|
569
|
-
But there are two differences:
|
569
|
+
But there are two differences:
|
570
570
|
|
571
571
|
(1) Each method needs to pass one more parameter `component_key`
|
572
572
|
(in the first parameter position),
|
@@ -575,7 +575,7 @@
|
|
575
575
|
```ruby
|
576
576
|
query! :UidQuery, :uid, String
|
577
577
|
```
|
578
|
-
This writing is feasible but not recommended,
|
578
|
+
This writing is feasible but not recommended,
|
579
579
|
because component's key and parameter's name seem easy to confuse.
|
580
580
|
The recommended writing is:
|
581
581
|
|
@@ -587,7 +587,7 @@
|
|
587
587
|
|
588
588
|
```ruby
|
589
589
|
# method signature
|
590
|
-
schema(component_key, type = nil,
|
590
|
+
schema(component_key, type = nil, **schema_info)
|
591
591
|
# usage
|
592
592
|
schema :Dog => [ String, desc: 'dogee' ] # <= schema_type is `String`
|
593
593
|
# advance usage
|
@@ -611,22 +611,22 @@
|
|
611
611
|
## Run! - Generate JSON Documentation File
|
612
612
|
|
613
613
|
Use `OpenApi.write_docs`:
|
614
|
-
|
614
|
+
|
615
615
|
```ruby
|
616
616
|
# initializer
|
617
617
|
OpenApi.write_docs generate_files: !Rails.env.production?
|
618
|
-
|
618
|
+
|
619
619
|
# or run directly in console
|
620
620
|
OpenApi.write_docs # will generate json doc files
|
621
621
|
```
|
622
|
-
|
622
|
+
|
623
623
|
Then the JSON files will be written to the directories you set. (Each API a file.)
|
624
624
|
|
625
625
|
## Use Swagger UI(very beautiful web page) to show your Documentation
|
626
626
|
|
627
|
-
Download [Swagger UI](https://github.com/swagger-api/swagger-ui) (version >= 2.3.0 support the OAS3)
|
628
|
-
to your project,
|
629
|
-
change the default JSON file path(url) in index.html.
|
627
|
+
Download [Swagger UI](https://github.com/swagger-api/swagger-ui) (version >= 2.3.0 support the OAS3)
|
628
|
+
to your project,
|
629
|
+
change the default JSON file path(url) in index.html.
|
630
630
|
In order to use it, you may have to enable CORS, [see](https://github.com/swagger-api/swagger-ui#cors-support)
|
631
631
|
|
632
632
|
## Tricks
|
@@ -636,39 +636,39 @@
|
|
636
636
|
Does your documentation take too many lines?
|
637
637
|
Do you want to separate documentation from business controller to simplify both?
|
638
638
|
Very easy! Just follow
|
639
|
-
|
639
|
+
|
640
640
|
```ruby
|
641
641
|
# config/initializers/open_api.rb
|
642
642
|
# in your configuration
|
643
643
|
base_doc_class: ApiDoc
|
644
|
-
|
644
|
+
|
645
645
|
# app/api_doc/api_doc.rb
|
646
646
|
require 'open_api/dsl'
|
647
|
-
|
647
|
+
|
648
648
|
class ApiDoc < Object
|
649
649
|
include OpenApi::DSL
|
650
650
|
end
|
651
|
-
|
651
|
+
|
652
652
|
# app/api_doc/v1/examples_doc.rb
|
653
653
|
class V1::ExamplesDoc < ApiDoc
|
654
654
|
route_base 'api/v1/examples'
|
655
|
-
|
655
|
+
|
656
656
|
api :index do
|
657
657
|
# ...
|
658
658
|
end
|
659
659
|
end
|
660
660
|
```
|
661
|
-
|
661
|
+
|
662
662
|
Notes: file name ends in `_doc.rb` by default, but you can change via `Config.doc_location`
|
663
663
|
(it should be file paths, defaults to `./app/**/*_doc.rb`).
|
664
664
|
|
665
665
|
### Trick2 - Global DRYing
|
666
666
|
|
667
667
|
Method `api_dry` is for DRY but its scope is limited to the current controller.
|
668
|
-
|
668
|
+
|
669
669
|
I have no idea of best practices, But you can look at this [file](documentation/examples/auto_gen_doc.rb).
|
670
670
|
The implementation of the file is: do `api_dry` when inherits the base controller inside `inherited` method.
|
671
|
-
|
671
|
+
|
672
672
|
You can use `sort` to specify the order of parameters.
|
673
673
|
|
674
674
|
### Trick3 - Auto Generate Description
|
@@ -677,19 +677,19 @@
|
|
677
677
|
desc 'api desc',
|
678
678
|
search_type!: 'search field, allows:<br/>'
|
679
679
|
query :search_type, String, enum: %w[name creator category price]
|
680
|
-
|
680
|
+
|
681
681
|
# or
|
682
|
-
|
682
|
+
|
683
683
|
query :search_type, String, desc!: 'search field, allows:<br/>',
|
684
684
|
enum: %w[name creator category price]
|
685
685
|
```
|
686
|
-
|
686
|
+
|
687
687
|
Notice `!` use (`search_type!`, `desc!`), it tells ZRO to append
|
688
688
|
information that analyzed from definitions (enum, must_be ..) to description automatically.
|
689
|
-
|
690
|
-
Any one of above will generate:
|
689
|
+
|
690
|
+
Any one of above will generate:
|
691
691
|
> search field, allows:<br/>1/ name<br/>2/ creator,<br/>3/ category<br/>4/ price<br/>
|
692
|
-
|
692
|
+
|
693
693
|
You can also use Hash to define `enum`:
|
694
694
|
```ruby
|
695
695
|
query :view, String, desc: 'allows values<br/>', enum!: {
|
@@ -708,27 +708,27 @@
|
|
708
708
|
```ruby
|
709
709
|
api :index, 'desc', skip: [ :Token ]
|
710
710
|
```
|
711
|
-
|
711
|
+
|
712
712
|
Look at this [file](documentation/examples/goods_doc.rb) to learn more.
|
713
713
|
|
714
714
|
### Trick5 - Auto Generate index/show Actions's Response-Types Based on DB Schema
|
715
715
|
|
716
716
|
Use method `load_schema` in `api_dry`.
|
717
|
-
|
717
|
+
|
718
718
|
See this [file](documentation/examples/auto_gen_doc.rb#L51) for uasge information.
|
719
719
|
|
720
720
|
### Trick6 - Combined Schema (one_of / all_of / any_of / not)
|
721
721
|
|
722
722
|
```ruby
|
723
723
|
query :combination, one_of: [ :GoodSchema, String, { type: Integer, desc: 'integer input' } ]
|
724
|
-
|
725
|
-
form
|
724
|
+
|
725
|
+
form data: {
|
726
726
|
:combination_in_form => { any_of: [ Integer, String ] }
|
727
727
|
}
|
728
|
-
|
728
|
+
|
729
729
|
schema :PetSchema => [ not: [ Integer, Boolean ] ]
|
730
730
|
```
|
731
|
-
|
731
|
+
|
732
732
|
OAS: [link1](https://swagger.io/docs/specification/data-models/oneof-anyof-allof-not/),
|
733
733
|
[link2](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaObject)
|
734
734
|
|
@@ -737,7 +737,7 @@
|
|
737
737
|
- **You wrote document of the current API, but not find in the generated json file?**
|
738
738
|
Check your routing settings.
|
739
739
|
- **Undefine method `match?`**
|
740
|
-
Monkey patches for `String` and `Symbol`:
|
740
|
+
Monkey patches for `String` and `Symbol`:
|
741
741
|
```ruby
|
742
742
|
class String # Symbol
|
743
743
|
def match?(pattern); !match(pattern).nil? end
|
@@ -745,7 +745,7 @@
|
|
745
745
|
```
|
746
746
|
- **Report error when require `routes.rb`?***
|
747
747
|
1. Run `rails routes`.
|
748
|
-
2. Copy the output to a file, for example `config/routes.txt`.
|
748
|
+
2. Copy the output to a file, for example `config/routes.txt`.
|
749
749
|
Ignore the file `config/routes.txt`.
|
750
750
|
3. Put `c.rails_routes_file = 'config/routes.txt'` to your ZRO config.
|
751
751
|
|
@@ -753,10 +753,10 @@
|
|
753
753
|
## About `OpenApi.docs` and `OpenApi.routes_index`
|
754
754
|
|
755
755
|
After `OpenApi.write_docs`, the above two module variables will be generated.
|
756
|
-
|
756
|
+
|
757
757
|
`OpenApi.docs`: A Hash with API names as keys, and documents of each APIs as values.
|
758
758
|
documents are instances of ActiveSupport::HashWithIndifferentAccess.
|
759
|
-
|
759
|
+
|
760
760
|
`OpenApi.routes_index`: Inverted index of controller path to API name mappings.
|
761
761
|
Like: `{ 'api/v1/examples' => :homepage_api }`
|
762
762
|
It's useful when you want to look up a document based on a controller and do something.
|
@@ -764,7 +764,7 @@
|
|
764
764
|
## Development
|
765
765
|
|
766
766
|
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.
|
767
|
-
|
767
|
+
|
768
768
|
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).
|
769
769
|
|
770
770
|
## License
|