{"id":13879155,"url":"https://github.com/zhandao/zero-rails_openapi","last_synced_at":"2025-04-04T06:06:44.001Z","repository":{"id":47716909,"uuid":"103143995","full_name":"zhandao/zero-rails_openapi","owner":"zhandao","description":"Concise DSL for generating OpenAPI Specification 3 (OAS3) JSON documentation for Ruby application.","archived":false,"fork":false,"pushed_at":"2024-05-28T15:12:34.000Z","size":414,"stargazers_count":171,"open_issues_count":8,"forks_count":20,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-28T05:08:02.598Z","etag":null,"topics":["api-documentation-tool","oas","openapi-specification","rails","ruby","swagger","zero"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zhandao.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-09-11T14:09:24.000Z","updated_at":"2025-01-31T18:41:01.000Z","dependencies_parsed_at":"2024-06-18T22:57:35.515Z","dependency_job_id":null,"html_url":"https://github.com/zhandao/zero-rails_openapi","commit_stats":{"total_commits":126,"total_committers":10,"mean_commits":12.6,"dds":0.3492063492063492,"last_synced_commit":"2a32ca8ff8aae85ecd02c011dc4af4a171b49f07"},"previous_names":[],"tags_count":38,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zhandao%2Fzero-rails_openapi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zhandao%2Fzero-rails_openapi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zhandao%2Fzero-rails_openapi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zhandao%2Fzero-rails_openapi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zhandao","download_url":"https://codeload.github.com/zhandao/zero-rails_openapi/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247128737,"owners_count":20888234,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-documentation-tool","oas","openapi-specification","rails","ruby","swagger","zero"],"created_at":"2024-08-06T08:02:11.530Z","updated_at":"2025-04-04T06:06:43.978Z","avatar_url":"https://github.com/zhandao.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"# ZRO: OpenApi 3 JSON-Doc Generator for Rails\n\n  [![Gem Version](https://badge.fury.io/rb/zero-rails_openapi.svg)](https://badge.fury.io/rb/zero-rails_openapi)\n  [![Build Status](https://travis-ci.org/zhandao/zero-rails_openapi.svg?branch=master)](https://travis-ci.org/zhandao/zero-rails_openapi)\n  [![Maintainability](https://api.codeclimate.com/v1/badges/471fd60f6eb7b019ceed/maintainability)](https://codeclimate.com/github/zhandao/zero-rails_openapi/maintainability)\n  [![Test Coverage](https://api.codeclimate.com/v1/badges/471fd60f6eb7b019ceed/test_coverage)](https://codeclimate.com/github/zhandao/zero-rails_openapi/test_coverage)\n\n  Concise DSL for generating OpenAPI Specification 3 (**OAS3**, formerly Swagger3) JSON documentation for Rails application.\n  \n  ```ruby\n  class Api::ExamplesController \u003c ApiController\n    api :update, 'POST update some thing' do\n      path  :id, Integer\n      query :token, String, desc: 'api token', length: 16\n      form data: { phone: String }\n    end\n  end\n  ```\n\n## Contributing\n\n  **Hi, here is ZhanDao = ▽ =  \n  It may be a very useful tool if you want to write API document clearly.  \n  I'm looking forward to your issue and PR!**\n  \n  (Test cases are rich, like: [api DSL](spec/api_spec.rb) and [schema Obj](spec/oas_objs/schema_obj_spec.rb))\n\n## Table of Contents\n\n- [About OAS](#about-oas) (OpenAPI Specification)\n- [Installation](#installation)\n- [Configure](#configure)\n- [DSL Usage](#dsl-usage)\n  - [a.Basic DSL](#basic-dsl)\n    - [a.1. route_base](#1-route_base-required-if-youre-not-writing-dsl-in-controller)\n    - [a.2. doc_tag](#2-doc_tag-optional)\n    - [a.3. components](#3-components-optional)\n    - [a.4. api](#4-api-required)\n    - [a.5. api_dry](#5-api_dry-optional)\n  - [b. DSLs written inside `api` and `api_dry`'s block](#dsls-written-inside-api-and-api_drys-block)\n    - [b.1. this_api_is_invalid!](#1-this_api_is_invalid-and-its-aliases)\n    - [b.2. desc](#2-desc-description-for-the-current-api)\n    - [b.3. param family methods](#3-param-family-methods-oas---parameter-object)\n    - [b.4. request_body family methods](#4-request_body-family-methods-oas---request-body-object)\n    - [b.5. response family methods](#5-response-family-methods-oas---response-object)\n    - [b.6. callback](#6-callback-oas---callback-object)\n    - [b.7. Authentication and Authorization](#7-authentication-and-authorization)\n    - [b.8. server](#8-overriding-global-servers-by-server)\n    - [b.9. dry](#9-dry)\n  - [c. DSLs written inside `components`'s block](#dsls-written-inside-componentss-block)\n  - [d. Schema and Type](#schema-and-type)\n    - [d.1. (Schema) Type](#schema-type)\n    - [d.2. Schema](#schema)\n    - [d.3. Combined Schema](#combined-schema)\n- [Run! - Generate JSON documentation file](#run---generate-json-documentation-file)\n- [Use Swagger UI(very beautiful web page) to show your Documentation](#use-swagger-uivery-beautiful-web-page-to-show-your-documentation)\n- [Tricks](#tricks)\n    - [Write DSL somewhere else](#trick1---write-the-dsl-somewhere-else)\n    - [Global DRYing](#trick2---global-drying)\n    - [Auto generate description form enum](#trick3---auto-generate-description-form-enum)\n    - [Skip or Use parameters define in `api_dry`](#trick4---skip-or-use-parameters-define-in-api_dry)\n    - [Atuo Generate index/show Actions's Responses Based on DB Schema](#trick5---auto-generate-indexshow-actionss-response-types-based-on-db-schema)\n- [Troubleshooting](#troubleshooting)\n- [About `OpenApi.docs` and `OpenApi.routes_index`](#about-openapidocs-and-openapiroutes_index)\n\n## About OAS\n\n  Everything about OAS3 is on [OpenAPI Specification](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md)\n\n  You can getting started from [swagger.io](https://swagger.io/docs/specification/basic-structure/)\n\n  **I suggest you should understand the basic structure of OAS3 at least.**\n  such as component (can help you reuse DSL code, when your apis are used with the\n  same data structure).\n\n## Installation\n\n  Add this line to your Rails's Gemfile:\n\n  ```ruby\n  gem 'zero-rails_openapi'\n  # or\n  gem 'zero-rails_openapi', github: 'zhandao/zero-rails_openapi'\n  ```\n\n  And then execute:\n\n      $ bundle\n\n## Configure\n\n  Create an initializer, configure ZRO and define your OpenApi documents.\n\n  This is the simplest example:\n\n  ```ruby\n  # in config/initializers/open_api.rb\n  require 'open_api'\n\n  OpenApi::Config.class_eval do\n    # Part 1: configs of this gem\n    self.file_output_path = 'public/open_api'\n\n    # Part 2: config (DSL) for generating OpenApi info\n    open_api :doc_name, base_doc_classes: [ApiDoc]\n    info version: '1.0.0', title: 'Homepage APIs'#, description: ..\n    # server 'http://localhost:3000', desc: 'Internal staging server for testing'\n    # bearer_auth :Authorization\n  end\n  ```\n  \n### Part 1: configs of this gem\n\n  1. `file_output_path`(required): The location where .json doc file will be output.\n  2. `default_run_dry`: defaults to run dry blocks even if the `dry` method is not called in the (Basic) DSL block. defaults to `false`.\n  3. `doc_location`: give regular expressions for file or folder paths. `Dir[doc_location]` will be `require` before document generates.\n      this option is only for not writing spec in controllers.\n  4. `rails_routes_file`: give a txt's file path (which's content is the copy of `rails routes`'s output). This will speed up document generation. \n  5. `model_base`: The parent class of models in your application. This option is for auto loading schema from database.\n  6. `file_format`\n\n### Part 2: config (DSL) for generating OpenApi info\n\n  ```ruby\n  # 1. open_api\n  #   base_doc_classes should be an array of base classes of the classes you write the OpenApi spec in, \n  #   like [ActionController::Base] (if you write spec in controllers).\n  open_api doc_name, base_doc_classes: []\n  \n  # 2. info\n  info version:, title:, desc: '', **addition\n  \n  # 3. server\n  # 4. security_scheme / base_auth / bearer_auth / api_key\n  # 5. global_security_require\n  ```\n\n  See all the DSLs: [config_dsl.rb](lib/open_api/config_dsl.rb)\n\n## DSL Usage\n\n  There are two kinds of DSL for this gem: **basic** and **inside basic**.\n  1. Basic DSLs are class methods which is for declaring your APIs, components, and spec code DRYing ...\n  2. DSLs written inside the block of Basic DSLs, is for declaring the parameters, responses (and so on) of the specified API and component.\n\n### First of all, `include OpenApi::DSL` in your base class (which is for writing spec):\n\n  For example:\n  ```ruby\n  # in app/controllers/api/api_controller.rb\n  class ApiController \u003c ActionController::API\n    include OpenApi::DSL\n  end\n  ```\n\n### DSL Usage Example\n\n  Here is the simplest usage:\n\n  ```ruby\n  class Api::ExamplesController \u003c ApiController\n    api :index, 'GET list' do\n      query :page, Integer#, range: { ge: 1 }, default: 1\n      query :rows, Integer#, desc: 'per page', range: { ge: 1 }, default: 10\n    end\n  end\n  ```\n\n### Basic DSL\n\n  [source code](lib/open_api/dsl.rb)\n\n#### (1) `route_base` [required if you're not writing DSL in controller]\n\n  ```ruby\n  # ** Method Signature\n  route_base path\n  # ** Usage\n  route_base 'api/v1/examples'\n  ```\n\n  [Usage](#trick1---write-the-dsl-somewhere-else): write the DSL somewhere else to simplify the current controller.\n\n#### (2) `doc_tag` [optional]\n\n  ```ruby\n  # ** Method Signature\n  doc_tag name: nil, **tag_info\n  # ** Usage\n  doc_tag name: 'ExampleTagName', description: \"ExamplesController's APIs\"#, externalDocs: ...\n  ```\n  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))\n  of all the APIs in the class.\n\n  Tag's name defaults to controller_name.\n\n#### (3) `components` [optional]\n\n  ```ruby\n  # ** Method Signature\n  components(\u0026block)\n  # ** Usage\n  components do\n    # (block inside) DSL for defining components\n    schema :DogSchema =\u003e [ { id: Integer, name: String }, dft: { id: 1, name: 'pet' } ]\n    query! :UidQuery  =\u003e [ :uid, String, desc: 'uid' ]\n    response :BadRqResp =\u003e [ 'bad request', :json ]\n  end\n\n  # to use component\n  api :action do\n    query :doge, :DogSchema # to use a Schema component\n    param_ref :UidQuery     # to use a Parameter component\n    response_ref :BadRqResp # to use a Response component\n  end\n  ```\n  Each RefObj is associated with components through component key.\n\n  We suggest that component keys should be camelized, and **must be Symbol**.\n\n#### (4) `api` [required]\n\n  For defining API (or we could say controller action).\n\n  ```ruby\n  # ** Method Signature\n  api action_name, summary = '', id: nil, tag: nil, http: nil, dry: Config.default_run_dry, \u0026block\n  # ** Usage\n  api :index, '(SUMMARY) this api blah blah ...', # block ...\n  ```\n  \n  Parameters explanation:\n  1. action_name: must be the same as controller action name\n  2. id: operationId\n  3. http: HTTP method (like: 'GET' or 'GET|POST')\n  \n#### (5) `api_dry` [optional]\n\n  This method is for DRYing.\n  The blocks passed to `api_dry` will be executed to the specified APIs which are having the actions or tags in the class.\n\n  ```ruby\n  # ** Method Signature\n  api_dry action_or_tags = :all, \u0026block\n  # ** Usage\n  api_dry :all, 'common response' # block ...\n  api_dry :index # block ...\n  api_dry :TagA # block ...\n\n  api_dry [:index, :show] do\n    query #...\n  end\n  ```\n  \n  And then you should call `dry` method ([detailed info](#9-dry)) for executing the declared dry blocks:\n  ```ruby\n  api :index do\n    dry\n  end\n  ```\n\n### DSLs written inside [api](#4-api-required) and [api_dry](#5-api_dry-optional)'s block\n\n  [source code](lib/open_api/dsl/api.rb)\n\n  These following methods in the block describe the specified API action: description, valid?,\n  parameters, request body, responses, securities and servers.\n\n  (Here corresponds to OAS [Operation Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#operationObject))\n\n#### (1) `this_api_is_invalid!`, and its aliases:\n  ```\n  this_api_is_expired!\n  this_api_is_unused!\n  this_api_is_under_repair!\n  ```\n\n  ```ruby\n  # ** Method Signature\n  this_api_is_invalid!(*)\n  # ** Usage\n  this_api_is_invalid! 'cause old version'\n  ```\n\n  After that, `deprecated` field of this API will be set to true.\n\n#### (2) `desc`: description for the current API\n\n  ```ruby\n  # ** Method Signature\n  desc string\n  # ** Usage\n  desc \"current API's description\"\n  ```\n\n#### (3) `param` family methods (OAS - [Parameter Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#parameterObject))\n\n  To define parameter for APIs.\n  ```\n  param                              # 1. normal usage\n  param_ref                          # 2. links sepcified RefObjs (by component keys) to current parameters.\n  header,  path,  query,  cookie     # 3. passes specified parameter location (like header) to `param`\n  header!, path!, query!, cookie!    # 4. bang method of above methods\n  in_* by: { parameter_definations } # 5. batch definition, such as `in_path`, `in_query`\n  examples                           # 6. examples of parameters\n  ```\n  **The bang method and param_name (which's name is end of a exclamation point `!`) means this param is required. Without `!` means optional. THE SAME BELOW.**\n\n  ```ruby\n  # Part 1\n  # param_type:  location of parameter, like: query, path [A]\n  # param_name:  name of parameter, it can be Symbol or String [B]\n  # schema_type: type of parameter, like: String, Integer (must be a constant). see #schema-and-type\n  # required:    :required / :req OR :optional / :opt\n  # schema:      see #schema-and-type (including combined schema)\n  # ** Method Signature\n  param param_type, param_name, schema_type, required, schema = { }\n  # ** Usage\n  param :query, :page, Integer, :req,  range: { gt: 0, le: 5 }, desc: 'page number'\n\n  # Part 2\n  # ** Method Signature\n  param_ref *component_key # should pass at least 1 key\n  # ** Usage\n  param_ref :IdPath#, :NameQuery, :TokenHeader\n\n  # Part 3 \u0026 4\n  # ** Method Signature\n  header param_name, schema_type = nil, **schema\n  query! param_name, schema_type = nil, **schema\n  # ** Usage\n  header :'X-Token', String\n  query! :readed, Boolean, default: false\n  # The same effect as above, but not concise\n  param :query, :readed, Boolean, :req, default: false\n\n  # Part 5 \n  # ** Method Signature\n  in_query **params_and_schema\n  # ** Usage\n  in_query(\n    search_type: String,\n     search_val: String,\n        export!: { type: Boolean, desc: 'export as pdf' }\n  )\n  # The same effect as above\n  query  :search_type, String\n  query  :search_val, String\n  query! :export, Boolean, desc: 'export as pdf'\n\n  # Part 6\n  # ** Method Signature\n  examples exp_params = :all, examples_hash\n  # ** Usage\n  # Suppose we have three parameters: id, name, age\n  # * normal\n  examples(\n    right_input: [ 1, 'user', 26 ],\n    wrong_input: [ 2, 'resu', 35 ]\n  )\n  # * using exp_params\n  examples [:id, :name], {\n    right_input: [ 1, 'user' ],\n    wrong_input: [ 2, 'resu' ]\n  }\n  ```\n\n  [A] OpenAPI 3.0 distinguishes between the following parameter types based on the parameter location: \n      **header, path, query, cookie**. [more info](https://swagger.io/docs/specification/describing-parameters/)\n\n  [B] If `param_type` is path, for example: if the API path is `/good/:id`, you have to declare a path parameter named `id`\n\n#### (4) `request_body` family methods (OAS - [Request Body Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#requestBodyObject))\n\n  OpenAPI 3.0 uses the requestBody keyword to distinguish the payload from parameters.\n  \n  Notice: Each API has only ONE request body object. Each request body object can has multiple media types.\n  It means: call `request_body` multiple times, (schemas) will be deeply merged (let's call it [fusion](#fusion)) into a request body object.\n  ```\n  request_body  # 1. normal usage\n  body_ref      # 2. it links sepcified RefObjs (by component keys) to the body.\n  body, body!   # 3. alias of request_body\n  form, form!   # 4. to define a multipart/form-data request_body\n  json, json!   # 5. to define a application/json request_body\n  data          # 5. to define [a] property in the form-data request_body\n  ```\n  Bang methods(!) means the specified media-type body is required.\n\n  ```ruby\n  # Part 1\n  # ** Method Signature\n  # a. `data` contains the attributes (params, or properties) and their schemas required by the request body\n  # b. `attr_name!` means it is required, without '!' means optional\n  # c. options: desc / exp_params and examples\n  # d. available `media_type` see: \n  #   https://github.com/zhandao/zero-rails_openapi/blob/master/lib/oas_objs/media_type_obj.rb#L29\n  request_body required, media_type, data: { }, desc: '', **options\n  # ** Usage\n  request_body :opt, :form, data: {\n    id!: Integer,\n    name: { type: String, desc: 'name' }\n  }, desc: 'a form-data'\n\n  # Part 2\n  # ** Method Signature\n  body_ref component_key\n  # ** Usage\n  body_ref :UpdateUserBody\n\n  # Part 3\n  # ** Method Signature\n  body! media_type, data: { }, **options\n  # ** Usage\n  body :json\n\n  # Part 4\n  # ** method Implement\n  def form data:, **options # or `form!`\n    body :form, data: data, **options\n  end\n  # ** Usage\n  form! data: {\n         name!: String,\n      password: { type: String, pattern: /[0-9]{6,10}/ },\n  }\n  json data: { name!: String }\n\n  # Part 5\n  # ** Method Signature\n  data name, type = nil, schema = { }\n  # ** Usage\n  data :password!, String, pattern: /[0-9]{6,10}/\n  ```\n\n  \u003ca name=\"fusion\"\u003e\u003c/a\u003e \n  How **fusion** works:\n  1. Difference media types will be merged into `requestBody[\"content\"]`\n\n  ```ruby\n  form data: { }\n  body :json, data: { }\n  # will generate: \"content\": { \"multipart/form-data\": { }, \"application/json\": { } }\n  ```\n\n  2. The same media-types will be deeply merged together, including their `required` array:  \n     (So that you can call `form` multiple times)\n\n  ```ruby\n  data :param_a!, String\n  data :param_b,  Integer\n  # or same as:\n  form data: { :param_a! =\u003e String }\n  form data: { :param_b  =\u003e Integer }\n  # will generate: { \"param_a\": { \"type\": \"string\" }, \"param_b\": { \"type\": \"integer\" } } (call it X)\n  # therefore:\n  #   \"content\": { \"multipart/form-data\":\n  #     { \"schema\": { \"type\": \"object\", \"properties\": { X }, \"required\": [ \"param_a\" ] }\n  #   }\n  ```\n\n#### (5) `response` family methods (OAS - [Response Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#response-object))\n\n  To define the response for APIs.\n  ```\n  response      # 1. aliases: `resp` and `error`\n  response_ref  # 2. it links sepcified RefObjs (by component keys) to the response.\n  ```\n\n  ```ruby\n  # ** Method Signature\n  response code, desc, media_type = nil, headers: { }, data: { }, **options\n  # ** Usage\n  resp 200, 'success', :json, data: { name: 'test' }\n  response 200, 'query result', :pdf, data: File\n  response :success, 'succ', :json, headers: { 'X-Request-Start': String }, data: { }\n\n  # ** Method Signature\n  response_ref code_and_compkey_hash\n  # ** Usage\n  response_ref 700 =\u003e :AResp, 800 =\u003e :BResp\n  ```\n\n### (6) Callback (OAS - [Callback Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#callback-object))\n\n  [About Callbacks](https://swagger.io/docs/specification/callbacks/)\n  \u003e In OpenAPI 3 specs, you can define callbacks – asynchronous, out-of-band requests that your service will send to some other service in response to certain events. This helps you improve the workflow your API offers to clients.  \n    A typical example of a callback is a subscription functionality ... you can define the format of the “subscription” operation as well as the format of callback messages and expected responses to these messages.  \n    This description will simplify communication between different servers and will help you standardize use of webhooks in your API.  \n  [Complete YAML Example](https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v3.0/callback-example.yaml)\n  \n  The structure of Callback Object:\n  ```\n  callbacks:\n    Event1:\n      path1:\n        ...\n      path2:\n       ...\n    Event2:\n      ...\n  ```\n  \n  `callback` method is for defining callbacks.\n  ```ruby\n  # ** Method Signature\n  callback event_name, http_method, callback_url, \u0026block\n  # ** Usage\n  callback :myEvent, :post, 'localhost:3000/api/goods' do\n    query :name, String\n    data :token, String\n    response 200, 'success', :json, data: { name: String, description: String }\n  end\n  ```\n  \n  Use runtime expressions in callback_url:\n  ```ruby\n  callback :myEvent, :post, '{body callback_addr}/api/goods/{query id}'\n  # the final URL will be: {$request.body#/callback_addr}/api/goods/{$request.query.id}\n  # Note: Other expressions outside \"$request\" are not supported yet\n  ```\n\n#### (7) Authentication and Authorization\n\n  First of all, please make sure that you have read one of the following documents:\n  [OpenApi Auth](https://swagger.io/docs/specification/authentication/)\n  or [securitySchemeObject](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#securitySchemeObject)\n\n  ##### Define Security Scheme\n\n  Use these DSL **in your initializer config or `components` block**:\n  ```\n  security_scheme # alias `auth_scheme`\n  base_auth       # will call `security_scheme`\n  bearer_auth     # will call `security_scheme`\n  api_key         # will call `security_scheme`\n  ```\n  It's very simple to use (if you understand the above document)\n  ```ruby\n  # ** Method Signature\n  security_scheme scheme_name, other_info\n  # ** Usage\n  security_scheme :BasicAuth, { type: 'http', scheme: 'basic', desc: 'basic auth' }\n\n  # ** Method Signature\n  base_auth scheme_name, other_info = { }\n  bearer_auth scheme_name, format = 'JWT', other_info = { }\n  api_key scheme_name, field:, in:, **other_info\n  # ** Usage\n  base_auth :BasicAuth, desc: 'basic auth' # the same effect as above\n  bearer_auth :Token\n  api_key :ApiKeyAuth, field: 'X-API-Key', in: 'header', desc: 'pass api key to header'\n  ```\n\n  ##### Apply Security\n\n  ```\n  # Use in initializer (Global effectiveness)\n  global_security_require # alias: global_security \u0026 global_auth\n\n  # Use in `api`'s block (Only valid for the current controller)\n  security_require # alias security \u0026 auth_with\n  ```\n  ```ruby\n  # ** Method Signature\n  security_require scheme_name, scopes: [ ]\n  # ** Usage\n  global_auth :Token\n  auth_with   :OAuth, scopes: %w[ read_example admin ]\n  ```\n\n#### (8) Overriding Global Servers by `server`\n\n  ```ruby\n  # ** Method Signature\n  server url, desc: ''\n  # ** Usage\n  server 'http://localhost:3000', desc: 'local'\n  ```\n  \n#### (9) `dry`\n\n  You have to call `dry` method inside `api` block, or pass `dry: true` as parameter of `api`,\n  for executing the dry blocks you declared before. Otherwise nothing will happen.\n  \n  ```ruby\n  # ** Method Signature\n  dry only: nil, skip: nil, none: false\n  \n  # ** Usage\n  # In general, just:\n  dry\n  # To skip some params declared in dry blocks:\n  dry skip: [:id, :name]\n  # `only` is used to specify which parameters will be taken from dry blocks\n  dry only: [:id]\n  ```\n\n### DSLs written inside [components](#3-components-optional)'s block\n  [code source](lib/open_api/dsl/components.rb) (Here corresponds to OAS [Components Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#componentsObject))\n\n  Inside `components`'s block,\n  you can use the same DSLs as [DSLs written inside `api` and `api_dry`'s block](#dsls-written-inside-api-and-api_drys-block).  \n  But notice there are two differences:\n\n  (1) Each method needs to pass one more parameter `component_key` (as the first parameter),\n      it will be used as the reference name for the component.\n\n  ```ruby\n  query! :UidQuery, :uid, String， desc: 'it is a component'\n  #         ↑         ↑\n  # component_key  param_name\n  \n  # You can also use \"arrow writing\", it may be easier to understand\n  query! :UidQuery =\u003e [:uid, String, desc: '']\n  ```\n\n  (2) You can use `schema` to define a Schema Component.\n\n  ```ruby\n  # ** Method Signature\n  schema component_key, type = nil, **schema\n  # ** Usage\n  schema :Dog  =\u003e [ String, desc: 'doge' ]\n  # advance usage\n  schema :Dog =\u003e [\n      {\n           id!: Integer,\n          name: { type: String, desc: 'doge name' }\n      }, default: { id: 1, name: 'pet' }\n  ]\n  # or flatten writing\n  schema :Dog, { id!: Integer, name: String }, default: { id: 1, name: 'pet' }\n  #\n  # pass a ActiveRecord class constant as `component_key`,\n  #   it will automatically load schema from database and then generate the component.\n  schema User # easy! And the component_key will be :User\n  ```\n  To enable load schema from database, you must set [model base](#part-1-configs-of-this-gem) correctly.\n  \n### Schema and Type\n\n  schema and type -- contain each other\n\n#### (Schema) Type\n\n  Support all [data types](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#dataTypes) in OAS.   \n\n  1. String / 'binary' / 'base64' / 'uri'\n  2. Integer / Long / 'int32' / 'int64' / Float / Double\n  3. File (it will be converted to `{ type: 'string', format: Config.file_format }`)\n  4. Date / DateTime\n  5. 'boolean'\n  6. Array / Array[\\\u003cType\\\u003e] (like: `Array[String]`, `[String]`)\n  7. Nested Array (like: `[[[Integer]]]`)\n  8. Object / Hash (Object with properties)  \n     Example: `{ id!: Integer, name: String }`\n  9. Nested Hash: `{ id!: Integer, name: { first: String, last: String } }`\n  10. Nested Array[Nested Hash]: `[[{ id!: Integer, name: { first: String, last: String } }]]`\n  11. Symbol Value: it will generate a Schema Reference Object link to the component correspond to ComponentKey, like: :IdPath, :NameQuery\n  \n  **Notice** that Symbol is not allowed in all cases except 11.\n  \n#### Schema\n\n  [OAS Schema Object](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#schemaObject)\n  and [source code](https://github.com/zhandao/zero-rails_openapi/blob/master/lib/oas_objs/schema_obj.rb)\n  \n  Schema (Hash) is for defining properties of parameters, responses and request bodies.\n  \n  The following property keys will be process slightly:\n  1. desc / description / d\n  2. enum / in / values / allowable_values  \n     should be Array or Range\n  3. range: allow value in this continuous range  \n     should be Range or like `{ gt: 0, le: 5 }`\n  4. length / size / lth  \n     should be an Integer, Integer Array, Integer Range, \n     or the following format Symbol: `:gt_`, `:ge_`, `:lt_`, `:le_` (:ge_5 means \"greater than or equal 5\"; :lt_9 means \"lower than 9\")\n  5. pattern / regxp\n  6. additional_properties / add_prop / values_type\n  7. example\n  8. examples\n  9. format\n  10. default: default value\n  11. type\n\n  The other keys will be directly merged. Such as:\n  1. `title: 'Property Title'`\n  2. `myCustomKey: 'Value'`\n\n#### Combined Schema\n\n  Very easy to use:\n  ```ruby\n  query :combination, one_of: [ :GoodSchema, String, { type: Integer, desc: 'integer input' } ]\n\n  form data: {\n      :combination_in_form =\u003e { any_of: [ Integer, String ] }\n  }\n\n  schema :PetSchema =\u003e [ not: [ Integer, Boolean ] ]\n  ```\n\n  OAS: [link1](https://swagger.io/docs/specification/data-models/oneof-anyof-allof-not/),\n  [link2](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaObject)\n\n## Run! - Generate JSON Documentation File\n\n  Use `OpenApi.write_docs`:\n\n  ```ruby\n  OpenApi.write_docs# if: !Rails.env.production?\n  ```\n\n  `if` option is used to control whether a JSON document is generated or not.\n  \n  Then the JSON files will be written to the directories you set. (Each API a file.)\n\n## Use Swagger UI(very beautiful web page) to show your Documentation\n\n  Download [Swagger UI](https://github.com/swagger-api/swagger-ui) (version \u003e= 2.3.0 support the OAS3)\n  to your project,\n  change the default JSON file path(url) in index.html.\n  In order to use it, you may have to enable CORS, [see](https://github.com/swagger-api/swagger-ui#cors-support)\n\n## Tricks\n\n### Trick1 - Write the DSL Somewhere Else\n\n  Does your documentation take too many lines?  \n  Do you want to separate documentation from controller to simplify both?  \n  Very easy! Just follow\n\n  ```ruby\n  # config/initializers/open_api.rb\n  # in your configuration\n  base_doc_classes: [ApiDoc]\n\n  # app/api_doc/api_doc.rb\n  require 'open_api/dsl'\n\n  class ApiDoc \u003c Object\n    include OpenApi::DSL\n  end\n\n  # app/api_doc/v1/examples_doc.rb\n  class V1::ExamplesDoc \u003c ApiDoc\n    route_base 'api/v1/examples'\n\n    api :index do\n      # ...\n    end\n  end\n  ```\n\n  Explain: These four steps are necessary:\n  1. create a class, like ApiDoc, and make it include OpenApi::DSL (then it could be the base class for writing Api spec).\n  2. set the specified Api spec's base_doc_classes to ApiDoc.\n  3. let your doc class (like V1::ExamplesDoc) inherit the base_doc_classes (ApiDoc).\n  4. set the route_base (to route path api/v1/examples of that controller Api::V1::ExamplesController) inside V1::ExamplesDoc.\n  \n  Notes: file name ends in `_doc.rb` by default, but you can change it by setting `Config.doc_location`\n    (it should be file paths, defaults to `./app/**/*_doc.rb`).\n\n### Trick2 - Global DRYing\n\n  Method `api_dry` is for DRY but its scope is limited to the current controller.\n\n  I have no idea of best practices, But you can look at this [file](examples/auto_gen_doc.rb).  \n  The implementation of the file is: do `api_dry` when inherits the base controller inside `inherited` method.\n\n  You can use `sort` to specify the order of parameters.\n\n### Trick3 - Auto Generate Description from Enum\n\n  Just use `enum!`:\n  ```ruby\n  query :search_type, String, desc: 'search field, allows：\u003cbr/\u003e', enum!: %w[name creator category price]\n  # it will generate: \n  \"search field, allows：\u003cbr/\u003e1/ name\u003cbr/\u003e2/ creator,\u003cbr/\u003e3/ category\u003cbr/\u003e4/ price\u003cbr/\u003e\"\n  ```\n  Or Hash `enum!`:\n  ```ruby\n  query :view, String, desc: 'allows values\u003cbr/\u003e', enum!: {\n          'all goods (default)': :all,\n                  'only online': :online,\n                 'only offline': :offline,\n              'expensive goods': :get,\n                  'cheap goods': :borrow,\n  }\n  ```\n\n## Troubleshooting\n\n- **You wrote document of the current API, but not find in the generated json file?**  \n  Check your routing settings.\n\n- **Report error when require `routes.rb`?***\n  1. Run `rails routes`.\n  2. Copy the output to a file, for example `config/routes.txt`.\n     Ignore the file `config/routes.txt`.\n  3. Put `c.rails_routes_file = 'config/routes.txt'` to your ZRO config.\n\n\n## About `OpenApi.docs` and `OpenApi.routes_index`\n\n  After `OpenApi.write_docs`, the above two module variables will be generated.\n\n  `OpenApi.docs`: A Hash with API names as keys, and documents of each APIs as values.  \n  documents are instances of ActiveSupport::HashWithIndifferentAccess.\n\n  `OpenApi.routes_index`: Inverted index of controller path to API name mappings.  \n  Like: `{ 'api/v1/examples' =\u003e :homepage_api }`  \n  It's useful when you want to look up a document based on a controller and do something.\n\n## Development\n\n  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.\n\n  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).\n\n## License\n\n  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n\n## Code of Conduct\n\n  Everyone interacting in the Zero-RailsOpenApi project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](CODE_OF_CONDUCT.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzhandao%2Fzero-rails_openapi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzhandao%2Fzero-rails_openapi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzhandao%2Fzero-rails_openapi/lists"}