zero-rails_openapi 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 388bb78c95e92399dacc43b0a83ae3b5165e3ea2
4
- data.tar.gz: 352a5d7fdf9f6aa670a7e0ea56a99934dec0375c
3
+ metadata.gz: 4b90e9497b858c621362ea5413020a64bdbd59de
4
+ data.tar.gz: '067410229fdc842e1d2f65e3cf4fbb9482535044'
5
5
  SHA512:
6
- metadata.gz: 26b8d36f4601facd4ed6936e5be617a8cc03ee279c99c603727ad7fb7432841f2e9ad20691e1d1a0f6e448a837b758f55cf5e4408027b87cc25ce3bd7391a0c4
7
- data.tar.gz: bbfc3c14e4c72b8f56eed5dae4fb4df9c5120e81bd1c7d8a4fd535c0853a7e23d018812aabfa3283d51b421b8a8aee6d3ab84ef055087dbf6c418c5a1bb4a82d
6
+ metadata.gz: eefc1f9b19e39b1a7aee1f9817c9860da02b77f4feb94a22a72fa8dd11739e9e9b1cda3d23404bfeaefbeba9fd3a9cd2c06898f92a31f14c60eae3c1788b5b61
7
+ data.tar.gz: 1d5bf3b31a7e8ed246e50ecd63f869c0913185a0eb31c95490d32163f48ff5c0eba8e744ce4ec234ad72ff8821e3f246b515d0cec473cb3d4269eaf9c8bf11f5
data/Gemfile CHANGED
@@ -3,4 +3,4 @@ source "https://rubygems.org"
3
3
  git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  # Specify your gem's dependencies in zero-rails_openapi.gemspec
6
- gemspec
6
+ gemspec
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- zero-rails_openapi (1.0.0)
4
+ zero-rails_openapi (1.1.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -1,7 +1,29 @@
1
1
  # ZRO: OpenApi 3 DocGenerator for Rails
2
2
 
3
3
  Provide concise DSL for you to generate the OpenAPI Specification 3 (**OAS3**, formerly Swagger3) JSON file for Rails application,
4
- then you can use Swagger-UI 3.2.0+ to show the documentation.
4
+ then you can use Swagger UI 3.2.0+ to show the documentation.
5
+
6
+ ## Contributing
7
+
8
+ **Hi, here is ZhanDao. This gem was completed when I learned Ruby less than three months,
9
+ I'm not sure if it has problem, but it may have a lot to improve.
10
+ I'm looking forward to your issues and PRs, thanks!**
11
+
12
+ Currently, I think the most important TODO is the Unit Test (RSpec, I want is),
13
+ but I dont have enough time now = ▽ =
14
+
15
+ ## Table of Contents
16
+
17
+ - [About OAS](https://github.com/zhandao/zero-rails_openapi#about-oas) (OpenAPI Specification)
18
+ - [Installation](https://github.com/zhandao/zero-rails_openapi#installation)
19
+ - [Configure](https://github.com/zhandao/zero-rails_openapi#configure)
20
+ - [Usage](https://github.com/zhandao/zero-rails_openapi#usage)
21
+ - [DSL for documenting your controller](https://github.com/zhandao/zero-rails_openapi#dsl-for-documenting-your-controller)
22
+ - [Generate JSON Documentation File](https://github.com/zhandao/zero-rails_openapi#generate-json-documentation-file)
23
+ - [Use Swagger UI(very beautiful web page) to show your Documentation](https://github.com/zhandao/zero-rails_openapi#use-swagger-uivery-beautiful-web-page-to-show-your-documentation)
24
+ - [Tricks](#tricks)
25
+ - [Write the DSL Somewhere Else]
26
+ - [Troubleshooting](https://github.com/zhandao/zero-rails_openapi#troubleshooting)
5
27
 
6
28
  ## About OAS
7
29
 
@@ -45,7 +67,7 @@ OpenApi.configure do |c|
45
67
 
46
68
  c.register_apis = {
47
69
  homepage_api: {
48
- # [REQUIRED] ZRO will scan all the descendants of the root_controller, then generate their docs.
70
+ # [REQUIRED] ZRO will scan all the descendants of root_controller, then generate their docs.
49
71
  root_controller: Api::V1::BaseController,
50
72
 
51
73
  # [REQUIRED] OAS Info Object: The section contains API information.
@@ -67,7 +89,7 @@ end
67
89
  You can also set the *global configuration(/component)* of OAS:
68
90
  Server Object / Security Scheme Object / Security Requirement Object ...
69
91
 
70
- For more detailed configuration: [open_api.rb](https://github.com/zhandao/zero-rails_openapi/blob/master/lib/examples/open_api.rb)
92
+ For more detailed configuration: [open_api.rb](https://github.com/zhandao/zero-rails_openapi/blob/masterdocumentation/examples/open_api.rb)
71
93
 
72
94
  ## Usage
73
95
 
@@ -84,16 +106,16 @@ class ApplicationController < ActionController::API
84
106
  end
85
107
  ```
86
108
 
87
- #### \> [DSL Usage Example](https://github.com/zhandao/zero-rails_openapi/blob/master/lib/examples/examples_controller.rb)
109
+ #### \> [DSL Usage Example](https://github.com/zhandao/zero-rails_openapi/blob/masterdocumentation/examples/examples_controller.rb)
88
110
 
89
111
  ```ruby
90
112
  class Api::V1::ExamplesController < Api::V1::BaseController
91
113
  apis_set 'ExamplesController\'s APIs' do
92
114
  schema :Dog => [ { id!: Integer, name: String }, dft: { id: 1, name: 'pet' } ]
115
+ query! :QueryCompUuid => [ :product_uuid, String, desc: 'product uuid' ]
93
116
  path! :PathCompId => [ :id, Integer, desc: 'user id' ]
94
- query! :QueryCompUuid => [ :product_uuid, { uuid: String, time: 'int32' }, desc: 'product uuid' ]
95
- body! :RqBodyComp => [ :form ]
96
117
  resp :RespComp => [ 'bad request', :json ]
118
+ body! :RqBodyComp => [ :form ]
97
119
  end
98
120
 
99
121
  open_api_set %i[index show], 'common response' do
@@ -128,71 +150,202 @@ end
128
150
 
129
151
  #### \> Explanation
130
152
 
131
- ##### \>\> controller class methods ([code source](https://github.com/zhandao/zero-rails_openapi/blob/master/lib/open_api/dsl.rb))
153
+ #### \>\> controller class methods ([source code](https://github.com/zhandao/zero-rails_openapi/blob/master/lib/open_api/dsl.rb))
132
154
 
133
- - `apis_set` [Optional]
155
+ - `ctrl_path` (controller path) [Optional]
134
156
 
157
+ ```ruby
158
+ # method signature
159
+ ctrl_path path
160
+ # usage
161
+ ctrl_path 'api/v1/examples'
162
+ ```
163
+ This option 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)).
164
+ [Here's a trick](): Using `ctrl_path`, you can write the DSL somewhere else
165
+ to simplify the current controller.
166
+ \* Take the tag from `path.split('/').last`
135
167
 
168
+ - `apis_set` [Optional]
169
+
170
+ ```ruby
171
+ # method signature
172
+ apis_set desc = '', external_doc_url = '', &block
173
+ # usage
174
+ apis_set 'ExamplesController\'s APIs' do
175
+ # DSL for defining components
176
+ end
177
+ ```
178
+ desc and external_doc_url will be output to the tags[the current tag] (tag defaults to controller_name ), but are optional.
179
+ the focus is on the block, the DSL methods in the block will generate components.
136
180
 
137
181
  - `open_api_set` [Optional]
138
182
 
183
+ this method is for DRYing.
184
+
185
+ ```ruby
186
+ # method signature
187
+ open_api_set method = :all, desc = '', &block
188
+ # usage
189
+ open_api_set :all, 'common response' do; end
190
+ open_api_set :index do; end
191
+ open_api_set [:index, :show] do; end
192
+ ```
193
+
194
+ As you think, the DSL methods in the block will be executed to each API that you set by method.
195
+
196
+ - `open_api` [Required]
197
+
198
+ Define the specified API (in the following example is index).
199
+
200
+ ```ruby
201
+ # method signature
202
+ open_api method, summary = '', &block
203
+ # usage
204
+ open_api :index, '(SUMMARY) this api blah blah ...' do; end
205
+ ```
139
206
 
140
- - `open_api`
141
207
 
142
- ##### \>\> DSL methods inside *open_api* and *open_api_set*'s block ([code source](https://github.com/zhandao/zero-rails_openapi/blob/master/lib/open_api/dsl_inside_block.rb)# ApiInfoObj )
208
+ #### \>\> DSL methods inside *open_api* and *open_api_set*'s block ([source code](https://github.com/zhandao/zero-rails_openapi/blob/master/lib/open_api/dsl_inside_block.rb):: ApiInfoObj)
143
209
 
144
210
  These methods in the block describe the specified API(s): description, valid?,
145
211
  parameters, request body, responses, securities, servers.
146
212
 
213
+ (Here corresponds to OAS [Operation Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#operationObject))
214
+
147
215
  - `this_api_is_invalid!`, its aliases are:
148
216
  - `this_api_is_expired!`
149
217
  - `this_api_is_unused!`
150
218
  - `this_api_is_under_repair!`
151
219
 
152
- ```ruby
153
- # method signature
154
- this_api_is_invalid! explain = ''
155
- # usage
156
- this_api_is_invalid! 'this api is expired!'
157
- ```
220
+ ```ruby
221
+ # method signature
222
+ this_api_is_invalid! explain = ''
223
+ # usage
224
+ this_api_is_invalid! 'this api is expired!'
225
+ ```
158
226
 
159
227
  - `desc`: description for current API and its inputs (parameters and request body)
160
228
 
161
- ```ruby
162
- # method signature
163
- desc desc, inputs_descs = { }
164
- # usage
165
- desc 'current API\'s description',
166
- id: 'user id',
167
- email_addr: 'email_addr\'s desc'
168
- ```
229
+ ```ruby
230
+ # method signature
231
+ desc desc, inputs_descs = { }
232
+ # usage
233
+ desc 'current API\'s description',
234
+ id: 'user id',
235
+ email_addr: 'email_addr\'s desc'
236
+ ```
169
237
 
170
- You can of course describe the input in it's DSL method (like `query! :done` this line),
171
- but that will make it long and ugly. We recommend that unite descriptions in this place.
238
+ 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)),
239
+ but that will make it long and ugly. We recommend that unite descriptions in this place.
172
240
 
173
- - param family methods
241
+ - param family methods (OAS - [Parameter Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#parameterObject))
174
242
  - `param`
175
243
  - `param_ref`
176
- - `header`, `path`, `query`, `cookie`
177
- - bang methods: `header!`, `path!`, `query!`, `cookie!`
244
+ - `header`, `path`, `query`, `cookie` and bang methods: `header!`, `path!`, `query!`, `cookie!`
245
+ **The bang method(`!`) means it is required, so it is optional without `!`, the same below.**
246
+
247
+ Define the parameters for the API(operation).
248
+ You can use the Reference Object to link to parameters that are defined at the components/parameters by method param_ref().
249
+
250
+ ```ruby
251
+ # method signature
252
+ param param_type, name, type, required, schema_hash = { }
253
+ # usage
254
+ param :query, :page, Integer, :req, range: { gt: 0, le: 5 }, desc: 'page'
178
255
 
256
+ # method signature
257
+ param_ref component_key, *component_keys
258
+ # usage
259
+ param_ref :PathCompId
260
+ param_ref :PathCompId, :QueryCompUuid, ...
179
261
 
180
- - request_body family methods
262
+ # method signature
263
+ header name, type, schema_hash = { }
264
+ header! name, type, schema_hash = { }
265
+ query! name, type, schema_hash = { }
266
+ # usage
267
+ header! :'X-Token', String
268
+ query! :done, Boolean, must_be: false, default: true
269
+ ```
270
+
271
+ [**>> More About Param DSL <<**](https://github.com/zhandao/zero-rails_openapi/blob/master/documentation/parameter.md)
272
+
273
+ - request_body family methods (OAS - [Request Body Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#requestBodyObject))
181
274
  - `request_body`
182
275
  - `body_ref`
183
276
  - `body` and bang `body!`
277
+ - `form`, `form!`; `file`, `file!`
278
+
279
+ OpenAPI 3.0 uses the requestBody keyword to distinguish the payload from parameters.
280
+ Define the request body for the API(operation).
281
+ You can use the Reference Object to link to request body that is defined at the components/requestBodies by method body_ref().
282
+
283
+ ```ruby
284
+ # method signature
285
+ request_body required, media_type, desc = '', schema_hash = { }
286
+ # usage
287
+ request_body :opt, :form, type: { id!: Integer, name: String }
288
+
289
+ # method signature
290
+ body_ref component_key
291
+ # usage
292
+ body_ref :Body
293
+
294
+ # method signature
295
+ body(!) media_type, desc = '', schema_hash = { }
296
+ # usage
297
+ body :json
298
+
299
+ # method implement
300
+ def form desc = '', schema_hash = { }
301
+ body :form, desc, schema_hash
302
+ end
303
+
304
+ def file! media_type, desc = '', schema_hash = { type: File }
305
+ body! media_type, desc, schema_hash
306
+ end
307
+ ```
184
308
 
309
+ **Notice:** Each API can only declare a request body.
310
+ That is, all of the above methods you can only choose one of them.
185
311
 
186
- - response family methods
312
+ Media Type: We provide some [mapping](https://github.com/zhandao/zero-rails_openapi/blob/master/lib/oas_objs/media_type_obj.rb) from symbols to real media-types.
313
+
314
+ schema_hash: As above (see param), but more than a `type` (schema type).
315
+
316
+ - response family methods (OAS - [Response Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#response-object))
187
317
  - `response` (`resp`)
188
318
  - `response_ref`
189
319
  - `default_response` (`dft_resp`)
190
- - `error_response` (`other_response`, `oth_resp`, `error`, `err_resp`)
320
+ - `error_response` (`other_response`, `oth_resp`, `error`, `err_resp`): Are `response`'s aliases, should be used in the error response context.
321
+
322
+ Define the responses for the API(operation).
323
+ You can use the Response Object to link to request body that is defined at the components/responses by method response_ref().
324
+
325
+ ```ruby
326
+ # method signature
327
+ response code, desc, media_type = nil, schema_hash = { }
328
+ # usage
329
+ response '200', 'query result export', :pdf, type: File
330
+
331
+ # method signature
332
+ response_ref code_compkey_hash
333
+ # usage
334
+ response_ref '700' => :RespComp, '800' => :RespComp
335
+ ```
336
+
337
+ **practice:** Combined with wrong class, automatically generate error responses. TODO
191
338
 
192
- ##### \>\> DSL methods inside apis_set'block ([code source](https://github.com/zhandao/zero-rails_openapi/blob/master/lib/open_api/dsl_inside_block.rb)# CtrlInfoObj )
339
+ - security: TODO
340
+
341
+ - server: TODO
342
+
343
+ #### \>\> DSL methods inside apis_set'block ([code source](https://github.com/zhandao/zero-rails_openapi/blob/master/lib/open_api/dsl_inside_block.rb):: CtrlInfoObj )
344
+
345
+ (Here corresponds to OAS [Components Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#componentsObject))
193
346
 
194
347
  These methods in the block describe the current controller,
195
- or we say, these methods eventually produce reusable components.
348
+ in other words, these methods eventually produce reusable components.
196
349
 
197
350
  So, the following methods are used as above, except that you need to
198
351
  name the key of the component, and pass it as the first of argument list, like:
@@ -208,23 +361,74 @@ The recommended writing is:
208
361
  query! :QueryCompUuid => [:product_uuid, Integer, ...]
209
362
  ```
210
363
  The DSL methods used to generate the components in this block are:
211
- (explained above)
212
364
 
213
- - param family methods (except `param_ref`)
214
- - request_body family methods (except `body_ref`)
365
+ - param family methods (except `param_ref`) (explained above)
366
+ - request_body family methods (except `body_ref`) (explained above)
367
+ - schema: define Schema Object component.
368
+
369
+ ```ruby
370
+ # method signature
371
+ schema component_key, type, schema_hash
372
+ # usage
373
+ schema :Dog => [ { id!: Integer, name: String }, dft: { id: 1, name: 'pet' } ]
374
+ # or (unrecommended)
375
+ schema :Dog, { id!: Integer, name: String }, dft: { id: 1, name: 'pet' }
376
+ ```
215
377
 
378
+ ### Generate JSON Documentation File
216
379
 
380
+ Initializer or Console, run:
217
381
 
218
- ### Generate JSON Documentation File
382
+ ```ruby
383
+ OpenApi.write_docs
384
+ ```
219
385
 
386
+ Then the JSON files will be written to the directory you set. (Each API a file.)
220
387
 
221
- ### Use Swagger-UI(Very Beautiful Web UI) to show your Documentation
388
+ ### Use Swagger UI(very beautiful web page) to show your Documentation
222
389
 
390
+ Download [Swagger UI](https://github.com/swagger-api/swagger-ui) (version >= 2.3.0 support the OAS3)
391
+ to your project,
392
+ modify the default JSON file path(url) in the index.html
393
+ (window.onload >> SwaggerUIBundle >> url).
394
+ In order to use it, you may have to enable CORS, [see](https://github.com/swagger-api/swagger-ui#cors-support)
223
395
 
224
- ## Troubleshooting
396
+ ### Tricks
225
397
 
398
+ #### Write the DSL Somewhere Else (Recommend)
226
399
 
400
+ Does your documentation take too mant lines?
401
+ Do you want to separate documentation from business controller to simplify both?
402
+ Very easy! Just use `ctrl_path`.
227
403
 
404
+ ```ruby
405
+ # config/initializers/open_api.rb
406
+ # in your configure
407
+ root_controller: BaseDoc
408
+
409
+ # app/api_doc/base_doc.rb
410
+ require 'open_api/dsl'
411
+
412
+ class BaseDoc < Object
413
+ include OpenApi::DSL
414
+ end
415
+
416
+ # app/api_doc/v1/examples_doc.rb
417
+ class V1::ExamplesDoc < BaseDoc
418
+ ctrl_path 'api/v1/examples'
419
+
420
+ open_api :index do
421
+ # ...
422
+ end
423
+ end
424
+ ```
425
+
426
+ Notes: convention is the file name ends with `_doc.rb`
427
+
428
+ ## Troubleshooting
429
+
430
+ - **You wrote document of the current API, but not find in the generated json file?**
431
+ Check your routing settings.
228
432
 
229
433
  ## Development
230
434
 
@@ -232,10 +436,6 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
232
436
 
233
437
  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).
234
438
 
235
- ## Contributing
236
-
237
- Bug reports and pull requests are welcome on GitHub at https://github.com/zhandao/zero-rails_openapi. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
238
-
239
439
  ## License
240
440
 
241
441
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/README_zh.md ADDED
@@ -0,0 +1 @@
1
+ TODO = ▽ =
@@ -1,10 +1,10 @@
1
1
  class Api::V1::ExamplesController < Api::V1::BaseController
2
2
  apis_set 'ExamplesController\'s APIs' do
3
3
  schema :Dog => [ { id!: Integer, name: String }, dft: { id: 1, name: 'pet' } ]
4
+ query! :QueryCompUuid => [ :product_uuid, String, desc: 'product uuid' ]
4
5
  path! :PathCompId => [ :id, Integer, desc: 'user id' ]
5
- query! :QueryCompUuid => [ :product_uuid, { uuid: String, time: 'int32' }, desc: 'product uuid' ]
6
- body! :RqBodyComp => [ :form ]
7
6
  resp :RespComp => [ 'bad request', :json ]
7
+ body! :RqBodyComp => [ :form ]
8
8
  end
9
9
 
10
10
  open_api_set %i[index show], 'common response' do
@@ -53,11 +53,11 @@ OpenApi.configure do |c|
53
53
  # This URL supports Server Variables and MAY be relative,
54
54
  # to indicate that the host location is relative to the location where
55
55
  # the OpenAPI document is being served.
56
- url: 'http://localhost:2333/api/v1',
56
+ url: 'http://localhost:2333',
57
57
  # An optional string describing the host designated by the URL.
58
58
  description: 'Optional server description, e.g. Main (production) server'
59
59
  },{
60
- url: 'http://localhost:3332/api/v1',
60
+ url: 'http://localhost:3332',
61
61
  description: 'Optional server description, e.g. Internal staging server for testing'
62
62
  }],
63
63
 
@@ -0,0 +1,55 @@
1
+ ### More Explanation of Param()
2
+
3
+ - [param_type] OpenAPI 3.0 distinguishes between the following parameter types based on the parameter location:
4
+ **header, path, query, cookie**. [more](https://swagger.io/docs/specification/describing-parameters/)
5
+
6
+ - [name] parameter name. If param_type is :path, it must correspond to the associated path segment form
7
+ the routing path, for example: the path is `/good/:id`, then you have to declare a path parameter with name `id`.
8
+
9
+ - [type] parameter (schema) type. Support all [data types](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#dataTypes) defined in OAS.
10
+ In addition, you can use `format` in schema_hash to define in fine detail the data type being used, like:
11
+ int32, float, date ...
12
+ All the types you can use are:
13
+ - **String, 'binary', 'base64'**
14
+ - **Integer, Long, 'int32', 'int64', Float, Double**
15
+ - **File** (it will be converted as `{ type: 'string', format: OpenApi.config.dft_file_format }`)
16
+ - **Date, DateTime**
17
+ - **Boolean**
18
+ - **Array**: `Array[String]` or `[String]`
19
+ - Nested Array: `[[[Integer]]]`
20
+ - **Object**: you can use just `Object`, or use a hash to declare its properties `{ id!: Integer, name: String }`
21
+ (`!` bang key means it is required).
22
+ - Nested Object: `{ id!: Integer, name: { first: String, last: String } }`
23
+ - Nested Array and Object: `[[{ id!: Integer, name: { first: String, last: String } }]]`
24
+ - **:ComponentKey**: the Symbol value pass to type will generate a Schema Reference Object link
25
+ to the component correspond to ComponentKey.
26
+
27
+ You can use `Object.const_set()` to define a constant that does not exist, but note that
28
+ the value you set could not be a Symbol (it will be explained as a Ref Object), should be a String.
29
+
30
+ - [required] :opt or :req
31
+
32
+ - The [[schema]](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#schemaObject) defining the type used for the parameter.
33
+ schema_hash(optional) will be used to generate Schema Object inside Parameter Object.
34
+ [source code](https://github.com/zhandao/zero-rails_openapi/blob/master/lib/oas_objs/schema_obj.rb)
35
+ You can set the schema by following keys (all are optional), the words in parentheses are available aliases of the keys:
36
+ - enum (values, allowable_values)
37
+ Must be Array or Range(will be converted to Array)
38
+ - value (must_be, allowable_value)
39
+ Single value, could be a String, Array ...
40
+ - range (number_range)
41
+ Allow value in this continuous range. Set this field like this: `{ gt: 0, le: 5 }`
42
+ - length (lth)
43
+ Must be an Integer, Integer Array, Integer Range, or the following format Symbol: `:gt_`, `:ge_`, `:lt_`, `:le_`, examples: :ge_5 means "greater than or equal 5"; :lt_9 means "lower than 9".
44
+ - format (fmt)
45
+ - is (is_a)
46
+ 1. It's not in OAS, just an addition field for better express.You can see it as `format`, but in fact they are quite different.
47
+ 2. Look at this example: the `format` is set to "int32", but you also want to express that this
48
+ schema is an "id" format —— this cannot be expressed in the current OAS version.
49
+ 3. So I suggest that the value of `format` should related to data type, `is` should be an entity.
50
+ 4. ZRO defaults to identify whether `is` patterns matched the name, then automatically generate `is`.
51
+ for example the parameter name "user_email" will generate "is: email". Default `is` options are:
52
+ [email phone password uuid uri url time date], to overwrite it you can set it in initializer `c.is_options = %w[]`.
53
+ 5. If type is Object, for describing each property's schema, the only way is use ref type, like: `{ id: :Id, name: :Name }`
54
+ - pattern (regexp, pr, reg)
55
+ - default (dft, default_value)
@@ -51,7 +51,7 @@ module OpenApi
51
51
  { type: t }
52
52
  end
53
53
  end
54
- def recursive_obj_type(t) # DSL use { k:v } to represent object structure
54
+ def recursive_obj_type(t) # DSL use { prop_name: prop_type } to represent object structure
55
55
  return processed_type(t) unless t.is_a? Hash
56
56
 
57
57
  _schema = {
@@ -59,9 +59,9 @@ module OpenApi
59
59
  properties: { },
60
60
  required: [ ]
61
61
  }
62
- t.each do |k, v|
63
- _schema[:required] << "#{k}".delete('!') if "#{k}".match? '!'
64
- _schema[:properties]["#{k}".delete('!').to_sym] = recursive_obj_type v
62
+ t.each do |prop_name, prop_type|
63
+ _schema[:required] << "#{prop_name}".delete('!') if "#{prop_name}".match? '!'
64
+ _schema[:properties]["#{prop_name}".delete('!').to_sym] = recursive_obj_type prop_type
65
65
  end
66
66
  _schema.keep_if &value_present
67
67
  end
@@ -69,7 +69,8 @@ module OpenApi
69
69
  if t.is_a? Array
70
70
  {
71
71
  type: 'array',
72
- items: recursive_array_type(t[0])
72
+ # TODO: [[String], [Integer]] <= One Of? Object?(0=>[S], 1=>[I])
73
+ items: recursive_array_type(t.first)
73
74
  }
74
75
  else
75
76
  processed_type t
@@ -134,17 +135,18 @@ module OpenApi
134
135
  _value: %i[must_be value allowable_value ],
135
136
  _range: %i[range number_range ],
136
137
  _length: %i[length lth ],
137
- _is: %i[is_a is ], # NOT OAS Spec, just a addition
138
+ _is: %i[is_a is ], # NOT OAS Spec, just an addition
138
139
  _format: %i[format fmt ],
139
140
  _pattern: %i[pattern regexp pr reg ],
140
141
  _default: %i[default dft default_value ],
141
142
  }.each do |key, aliases|
142
143
  define_method key do
143
- aliases.each do |alias_name|
144
- break if self[key] == false
145
- self[key] ||= self[alias_name]
146
- end if self[key].nil?
147
- self[key]
144
+ self[key].tap do |it|
145
+ aliases.each do |alias_name|
146
+ break if it == false
147
+ it ||= self[alias_name]
148
+ end if it.nil?
149
+ end
148
150
  end
149
151
  define_method "#{key}=" do |value| self[key] = value end
150
152
  end
data/lib/open_api/dsl.rb CHANGED
@@ -8,10 +8,15 @@ module OpenApi
8
8
 
9
9
  # TODO: Doc-Block Comments
10
10
  module ClassMethods
11
+ def ctrl_path path
12
+ @_ctrl_path = path
13
+ @_apis_tag = path.split('/').last.camelize
14
+ end
15
+
11
16
  def apis_set desc = '', external_doc_url = '', &block
12
- @_api_infos, @_ctrl_infos = { }, { }
17
+ @_ctrl_infos = { }
13
18
  # current `tag`, this means that tags is currently divided by controllers.
14
- tag = @_ctrl_infos[:tag] = { name: controller_name.camelize }
19
+ tag = @_ctrl_infos[:tag] = { name: @_apis_tag ||= controller_name.camelize }
15
20
  tag[:description] = desc if desc.present?
16
21
  tag[:externalDocs] = { description: 'ref', url: external_doc_url } if external_doc_url.present?
17
22
 
@@ -20,38 +25,39 @@ module OpenApi
20
25
  end
21
26
 
22
27
  def open_api method, summary = '', &block
23
- # select the routing info corresponding to the current method from the routing list.
24
- action_path = "#{controller_path}##{method}"
28
+ apis_set if @_ctrl_infos.nil?
29
+
30
+ # select the routing info (corresponding to the current method) from the routing list.
31
+ action_path = "#{@_ctrl_path ||= controller_path}##{method}"
25
32
  routes_info = ctrl_routes_list.select { |api| api[:action_path].match? /^#{action_path}$/ }.first
26
- puts "[zero-rails_openapi] Routing mapping failed: #{controller_path}##{method}" or return if routes_info.nil?
33
+ puts "[zero-rails_openapi] Routing mapping failed: #{@_ctrl_path}##{method}" or return if routes_info.nil?
27
34
 
28
35
  # structural { path: { http_method:{ } } }, for Paths Object.
29
- # it will be merged into :paths
30
- path = @_api_infos[routes_info[:path]] ||= { }
36
+ path = (@_api_infos ||= { })[routes_info[:path]] ||= { }
31
37
  current_api = path[routes_info[:http_verb]] =
32
- ApiInfoObj.new(action_path).merge!( summary: summary, operationId: method, tags: [controller_name.camelize] )
38
+ ApiInfoObj.new(action_path).merge! summary: summary, operationId: method, tags: [@_apis_tag]
33
39
 
34
40
  current_api.tap do |it|
35
41
  it.instance_eval &block if block_given?
36
42
  [method, :all].each do |key| # blocks_store_key
37
- @apis_blocks[key]&.each { |blk| it.instance_eval &blk }
43
+ @_apis_blocks&.[](key)&.each { |blk| it.instance_eval &blk }
38
44
  end
39
45
  end
40
46
  end
41
47
 
42
48
  # For DRY; method could be symbol array
43
49
  def open_api_set method = :all, desc = '', &block
44
- @apis_blocks ||= { }
50
+ @_apis_blocks ||= { }
45
51
  if method.is_a? Array
46
- method.each { |m| (@apis_blocks[m.to_sym] ||= [ ]) << block }
52
+ method.each { |m| (@_apis_blocks[m.to_sym] ||= [ ]) << block }
47
53
  else
48
- (@apis_blocks[method.to_sym] ||= [ ]) << block
54
+ (@_apis_blocks[method.to_sym] ||= [ ]) << block
49
55
  end
50
56
  end
51
57
 
52
58
  def ctrl_routes_list
53
59
  @routes_list ||= Generator.generate_routes_list
54
- @routes_list[controller_path]
60
+ @routes_list[@_ctrl_path]
55
61
  end
56
62
  end
57
63
  end
@@ -9,7 +9,7 @@ module OpenApi
9
9
  module CommonDSL
10
10
  def arrow_writing_support
11
11
  Proc.new do |args, executor|
12
- if args.count == 1 && args[0].is_a?(Hash)
12
+ if args.count == 1 && args.first.is_a?(Hash)
13
13
  send(executor, args[0].keys.first, *args[0].values.first)
14
14
  else
15
15
  send(executor, *args)
@@ -26,12 +26,12 @@ module OpenApi
26
26
 
27
27
  %i[body body!].each do |method|
28
28
  define_method method do |*args|
29
- @_method_name = method
29
+ @method_name = method
30
30
  _request_body_agent *args
31
31
  end
32
32
  end
33
33
 
34
- # code represents `component_key` when u declare response component
34
+ # code represents `component_key` when declare response component
35
35
  def _response code, desc, media_type = nil, schema_hash = { }
36
36
  (self[:responses] ||= { }).merge! ResponseObj.new(code, desc, media_type, schema_hash).process
37
37
  end
@@ -45,9 +45,9 @@ module OpenApi
45
45
  end
46
46
 
47
47
  { # alias_methods mapping
48
- response: %i[resp error_response ],
49
- default_response: %i[dft_resp ],
50
- error_response: %i[other_response oth_resp error err_resp],
48
+ response: %i[error_response resp ],
49
+ default_response: %i[dft_resp dft_response ],
50
+ error_response: %i[other_response oth_resp error err_resp],
51
51
  }.each do |original_name, aliases|
52
52
  aliases.each do |alias_name|
53
53
  alias_method alias_name, original_name
@@ -91,7 +91,7 @@ module OpenApi
91
91
  end
92
92
 
93
93
  def _request_body_arg_agent component_key, media_type, desc = '', schema_hash = { }
94
- request_body component_key, ("#{@_method_name}".match?(/!/) ? :req : :opt), media_type, desc, schema_hash
94
+ request_body component_key, ("#{@method_name}".match?(/!/) ? :req : :opt), media_type, desc, schema_hash
95
95
  end
96
96
  end # ----------------------------------------- end of CtrlInfoObj
97
97
 
@@ -136,7 +136,7 @@ module OpenApi
136
136
  end
137
137
 
138
138
  def _request_body_agent media_type, desc = '', schema_hash = { }
139
- request_body ("#{@_method_name}".match?(/!/) ? :req : :opt), media_type, desc, schema_hash
139
+ request_body ("#{@method_name}".match?(/!/) ? :req : :opt), media_type, desc, schema_hash
140
140
  end
141
141
 
142
142
  def body_ref component_key
@@ -8,9 +8,10 @@ module OpenApi
8
8
 
9
9
  module ClassMethods
10
10
  def generate_docs(api_name = nil)
11
- Rails.application.eager_load!
11
+ Dir['./app/controllers/**/*.rb'].each { |file| require file }
12
+ Dir['./app/**/*_doc.rb'].each { |file| require file }
12
13
  if api_name.present?
13
- { api_name => generate_doc(api_name) }
14
+ [{ api_name => generate_doc(api_name) }]
14
15
  else
15
16
  OpenApi.apis.keys.map { |api_key| { api_key => generate_doc(api_key)} }.reduce({ }, :merge)
16
17
  end
@@ -27,17 +28,18 @@ module OpenApi
27
28
  })
28
29
 
29
30
  settings[:root_controller].descendants.each do |ctrl|
31
+ ctrl_infos = ctrl.instance_variable_get('@_ctrl_infos')
32
+ next if ctrl_infos.nil?
30
33
  doc[:paths].merge! ctrl.instance_variable_get('@_api_infos')
31
- doc[:tags] << ctrl.instance_variable_get('@_ctrl_infos')[:tag]
32
- doc[:components].merge! ctrl.instance_variable_get('@_ctrl_infos')[:components]
34
+ doc[:tags] << ctrl_infos[:tag]
35
+ doc[:components].merge! ctrl_infos[:components]
33
36
  end
34
37
  doc[:components].delete_if { |_,v| v.blank? }
35
- ($open_apis ||= { })[api_name] ||= HashWithIndifferentAccess.new doc.delete_if { |_,v| v.blank? }
38
+ ($open_apis ||= { })[api_name] ||= HashWithIndifferentAccess.new(doc.delete_if { |_,v| v.blank? })
36
39
  end
37
40
 
38
41
  def write_docs
39
42
  docs = generate_docs
40
- # puts docs
41
43
  output_path = OpenApi.config.file_output_path
42
44
  FileUtils.mkdir_p output_path
43
45
  docs.each do |api_name, doc|
@@ -1,3 +1,3 @@
1
1
  module OpenApi
2
- VERSION = '1.0.0'
2
+ VERSION = '1.1.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zero-rails_openapi
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - zhandao
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-09-22 00:00:00.000000000 Z
11
+ date: 2017-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -69,11 +69,13 @@ files:
69
69
  - Gemfile.lock
70
70
  - LICENSE.txt
71
71
  - README.md
72
+ - README_zh.md
72
73
  - Rakefile
73
74
  - bin/console
74
75
  - bin/setup
75
- - lib/examples/examples_controller.rb
76
- - lib/examples/open_api.rb
76
+ - documentation/examples/examples_controller.rb
77
+ - documentation/examples/open_api.rb
78
+ - documentation/parameter.md
77
79
  - lib/oas_objs/helpers.rb
78
80
  - lib/oas_objs/media_type_obj.rb
79
81
  - lib/oas_objs/param_obj.rb