[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-8016":3},{"id":4,"name":5,"fullName":6,"owner":5,"repo":5,"description":7,"homepage":8,"htmlUrl":8,"language":9,"languages":8,"totalLinesOfCode":8,"stars":10,"forks":11,"watchers":12,"openIssues":13,"contributorsCount":14,"subscribersCount":14,"size":14,"stars1d":14,"stars7d":15,"stars30d":16,"stars90d":14,"forks30d":14,"starsTrendScore":14,"compositeScore":17,"rankGlobal":8,"rankLanguage":8,"license":18,"archived":19,"fork":19,"defaultBranch":20,"hasWiki":21,"hasPages":19,"topics":22,"createdAt":8,"pushedAt":8,"updatedAt":25,"readmeContent":26,"aiSummary":27,"trendingCount":14,"starSnapshotCount":14,"syncStatus":28,"lastSyncTime":29,"discoverSource":30},8016,"rswag","rswag\u002Frswag","Seamlessly adds a Swagger to Rails-based API's",null,"Ruby",2199,460,27,21,0,1,3,60.79,"MIT License",false,"master",true,[23,5,24],"openapi","swagger-ui","2026-06-12 04:00:37","\u003C!-- cspell:ignore allof anyof oneof specifyingtesting -->\n\nrswag\n=========\n[![Build Status](https:\u002F\u002Fgithub.com\u002Frswag\u002Frswag\u002Factions\u002Fworkflows\u002Fruby.yml\u002Fbadge.svg?branch=master)](https:\u002F\u002Fgithub.com\u002Frswag\u002Frswag\u002Factions\u002Fworkflows\u002Fruby.yml?query=branch%3Amaster+)\n[![Maintainability](https:\u002F\u002Fapi.codeclimate.com\u002Fv1\u002Fbadges\u002F1175b984edc4610f82ab\u002Fmaintainability)](https:\u002F\u002Fcodeclimate.com\u002Fgithub\u002Frswag\u002Frswag\u002Fmaintainability)\n\nOpenApi 3.0 compatible!\n\nSeeking maintainers! Got a pet-bug that needs fixing? Just let us know in your issue\u002Fpr that you'd like to step up to help.\n\nRswag extends rspec-rails \"request specs\" with a Swagger-based DSL for describing and testing API operations. You describe your API operations with a succinct, intuitive syntax, and it automatically runs the tests. Once you have green tests, run a rake task to auto-generate corresponding OpenAPI files and expose them as YAML or JSON endpoints. Rswag also provides an embedded version of the awesome [swagger-ui](https:\u002F\u002Fgithub.com\u002Fswagger-api\u002Fswagger-ui) that's powered by the exposed file. This toolchain makes it seamless to go from integration specs, which you're probably doing in some form already, to living documentation for your API consumers.\n\nApi Rswag creates [Swagger](http:\u002F\u002Fswagger.io) tooling for Rails API's. Generate beautiful API documentation, including a UI to explore and test operations, directly from your rspec integration tests.\n\n\nAnd that's not all ...\n\nOnce you have an API that can describe itself in Swagger, you've opened the treasure chest of Swagger-based tools including a client generator that can be targeted to a wide range of popular platforms. See [swagger-codegen](https:\u002F\u002Fgithub.com\u002Fswagger-api\u002Fswagger-codegen) for more details.\n\n\u003C!-- START doctoc generated TOC please keep comment here to allow auto update -->\n**Table of Contents**\n\n- [rswag](#rswag)\n  - [Getting Started](#getting-started)\n  - [The rspec DSL](#the-rspec-dsl)\n    - [Paths, Operations and Responses](#paths-operations-and-responses)\n    - [Null Values](#null-values)\n    - [Support for oneOf, anyOf or AllOf schemas](#support-for-oneof-anyof-or-allof-schemas)\n    - [Global Metadata](#global-metadata)\n      - [Supporting multiple versions of API](#supporting-multiple-versions-of-api)\n      - [Formatting the description literals:](#formatting-the-description-literals)\n    - [Specifying\u002FTesting API Security](#specifyingtesting-api-security)\n  - [Configuration & Customization](#configuration--customization)\n    - [Output Location for Generated OpenAPI Files](#output-location-for-generated-openapi-files)\n    - [Input Location for Rspec Tests](#input-location-for-rspec-tests)\n    - [Referenced Parameters and Schema Definitions](#referenced-parameters-and-schema-definitions)\n    - [Request examples](#request-examples)\n    - [Response headers](#response-headers)\n      - [Nullable or Optional Response Headers](#nullable-or-optional-response-headers)\n    - [Response examples](#response-examples)\n    - [Enable auto generation examples from responses](#enable-auto-generation-examples-from-responses)\n      - [Dry Run Option](#dry-run-option)\n      - [Running tests without documenting](#running-tests-without-documenting)\n        - [rswag helper methods](#rswag-helper-methods)\n    - [Route Prefix for OpenAPI JSON Endpoints](#route-prefix-for-openapi-json-endpoints)\n    - [Root Location for OpenAPI Files](#root-location-for-openapi-files)\n    - [Dynamic Values for OpenAPI JSON](#dynamic-values-for-openapi-json)\n    - [Custom Headers for OpenAPI Files](#custom-headers-for-openapi-files)\n    - [Enable Swagger Endpoints for swagger-ui](#enable-swagger-endpoints-for-swagger-ui)\n    - [Enable Simple Basic Auth for swagger-ui](#enable-simple-basic-auth-for-swagger-ui)\n    - [Route Prefix for the swagger-ui](#route-prefix-for-the-swagger-ui)\n    - [Customizing the swagger-ui](#customizing-the-swagger-ui)\n    - [Serve UI Assets Directly from your Web Server](#serve-ui-assets-directly-from-your-web-server)\n\n\u003C!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n\n\n## Getting Started ##\n\n1. Add this line to your applications _Gemfile_:\n\n    ```ruby\n    gem 'rswag'\n    ```\n\n    or if you like to avoid loading rspec in other bundler groups load the rswag-specs component separately.\n    Note: Adding it to the :development group is not strictly necessary, but without it, generators and rake tasks must be preceded by RAILS_ENV=test.\n\n    ```ruby\n    # Gemfile\n    gem 'rswag-api'\n    gem 'rswag-ui'\n\n    group :development, :test do\n      gem 'rspec-rails'\n      gem 'rswag-specs'\n    end\n    ```\n\n2. Run the install generator\n\n    ```ruby\n    rails g rswag:install\n    ```\n\n    Or run the install generators for each package separately if you installed Rswag as separate gems, as indicated above:\n\n    ```ruby\n    rails g rswag:api:install\n    rails g rswag:ui:install\n    RAILS_ENV=test rails g rswag:specs:install\n    ```\n\n3. Create an integration spec to describe and test your API.\nThere is also a generator which can help get you started `rails generate rspec:swagger API::MyController`\n\n    ```ruby\n    # spec\u002Frequests\u002Fblogs_spec.rb\n    require 'openapi_helper'\n\n    describe 'Blogs API' do\n\n      path '\u002Fblogs' do\n\n        post 'Creates a blog' do\n          tags 'Blogs'\n          consumes 'application\u002Fjson'\n          parameter name: 'blog', in: :body, schema: {\n            type: :object,\n            properties: {\n              title: { type: :string },\n              content: { type: :string }\n            },\n            required: [ 'title', 'content' ]\n          }\n\n          response '201', 'blog created' do\n            let(:request_params) { { 'blog' => { title: 'foo', content: 'bar' } } } }\n            run_test!\n          end\n\n          response '422', 'invalid request' do\n            let(:request_params) { { 'blog' => { title: 'foo' } } }\n            run_test!\n          end\n        end\n      end\n\n      path '\u002Fblogs\u002F{id}' do\n\n        get 'Retrieves a blog' do\n          tags 'Blogs', 'Another Tag'\n          produces 'application\u002Fjson', 'application\u002Fxml'\n          parameter name: 'id', in: :path, type: :string\n          request_body_example value: { some_field: 'Foo' }, name: 'basic', summary: 'Request example description'\n\n          response '200', 'blog found' do\n            schema type: :object,\n              properties: {\n                id: { type: :integer },\n                title: { type: :string },\n                content: { type: :string }\n              },\n              required: [ 'id', 'title', 'content' ]\n\n            let(:request_params) { 'id' => { Blog.create(title: 'foo', content: 'bar').id } }\n            run_test!\n          end\n\n          response '404', 'blog not found' do\n            let(:request_params) { { 'id' => 'invalid' } }\n            run_test!\n          end\n\n          response '406', 'unsupported accept header' do\n            let(:request_headers) { { 'Accept' => 'application\u002Ffoo' } }\n            run_test!\n          end\n        end\n      end\n    end\n    ```\nBy default, the above command will create spec under _spec\u002Frequests_ folder. You can pass an option to change this default path as in `rails generate rspec:swagger API::BlogsController --spec_path integration`.\nThis will create the spec file _spec\u002Fintegration\u002Fblogs_spec.rb_\n\n4. Generate the OpenAPI JSON file(s)\n\n    ```ruby\n    rake rswag:specs:swaggerize\n    ```\n\n    This common command is also aliased as `rake rswag`.\n\n    Or if you installed your gems separately:\n    ```\n    RAILS_ENV=test rails rswag\n    ```\n\n5. Spin up your app and check out the awesome, auto-generated docs at _\u002Fapi-docs_!\n\n## The rspec DSL ##\n\n### Paths, Operations and Responses ###\n\nIf you've used [Swagger](http:\u002F\u002Fswagger.io\u002Fspecification) before, then the syntax should be very familiar. To describe your API operations, start by specifying a path and then list the supported operations (i.e. HTTP verbs) for that path. Path parameters must be surrounded by curly braces ({}). Within an operation block (see \"post\" or \"get\" in the example above), most of the fields supported by the [Swagger \"Operation\" object](http:\u002F\u002Fswagger.io\u002Fspecification\u002F#operationObject) are available as methods on the example group. To list (and test) the various responses for an operation, create one or more response blocks. Again, you can reference the [Swagger \"Response\" object](http:\u002F\u002Fswagger.io\u002Fspecification\u002F#responseObject) for available fields.\n\nTake special note of the __run_test!__ method that's called within each response block. This tells rswag to create and execute a corresponding example. It builds and submits a request based on parameter descriptions and corresponding values that have been provided using the `request_params` rspec variable. For example, the \"post\" description in the example above specifies a \"body\" parameter called \"blog\". It also lists 2 different responses. For the success case (i.e. the 201 response), notice how `request_params` is used to set the blog parameter to a value that matches the provided schema. For the failure case (i.e. the 422 response), notice how it's set to a value that does not match the provided schema. When the test is executed, rswag also validates the actual response code and, where applicable, the response body against the provided [JSON Schema](https:\u002F\u002Fjson-schema.org\u002Fspecification).\n\nIf you want to add metadata to the example, you can pass keyword arguments to the __run_test!__ method:\n\n```ruby\n# to run particular test case\nresponse '201', 'blog created' do\n  run_test! focus: true\nend\n\n# to write vcr cassette\nresponse '201', 'blog created' do\n  run_test! vcr: true\nend\n```\n\nIf you want to customize the description of the generated specification, a description can be passed to **run_test!**\n\n```ruby\nresponse '201', 'blog created' do\n  run_test! \"custom spec description\"\nend\n```\n\nIf you want to do additional validation on the response, pass a block to the __run_test!__ method:\n\n```ruby\nresponse '201', 'blog created' do\n  run_test! do |response|\n    data = JSON.parse(response.body)\n    expect(data['title']).to eq('foo')\n  end\nend\n```\n\nIf you'd like your specs to be a little more explicit about what's going on here, you can replace the call to __run_test!__ with equivalent \"before\" and \"it\" blocks:\n\n```ruby\nresponse '201', 'blog created' do\n  let(:request_params) { { 'blog' => { title: 'foo', content: 'bar' } } }\n\n  before do |example|\n    submit_request(example.metadata)\n  end\n\n  it 'returns a valid 201 response' do |example|\n    assert_response_matches_metadata(example.metadata)\n  end\nend\n```\n\nAlso note that the examples generated with __run_test!__ are tagged with the `:rswag` so they can easily be filtered. E.g. `rspec --tag rswag`\n\n### date-time in query parameters\n\nInput sent in queries of Rspec tests is HTML safe, including date-time strings.\n\n```ruby\nparameter name: 'date_time', in: :query, type: :string\n\nresponse '200', 'blog found' do\n  let(:date_time) { DateTime.new(2001, 2, 3, 4, 5, 6, '-7').to_s }\n  let(:request_params) { { 'date_time' => date_time } }\n\n  run_test! do\n    expect(request[:path]).to eq('\u002Fblogs?date_time=2001-02-03T04%3A05%3A06-07%3A00')\n  end\nend\n```\n\n### Enum description ###\nIf you want to output a description of each enum value, the description can be passed to each value:\n```ruby\nparameter name: 'status', in: :query,\n          enum: { 'draft': 'Retrieves draft blogs', 'published': 'Retrieves published blogs', 'archived': 'Retrieves archived blogs' },\n          description: 'Filter by status'\n\nresponse '200', 'success' do\n  let(:request_params) { {'status' => 'published'} }\n\n  run_test!\nend\n```\n\n### Schema validations\n\n#### Additional properties\nIf you want to disallow additional properties in response body, you can set the option `openapi_no_additional_properties` to true:\n\n```ruby\n# spec\u002Fswagger_helper.rb\nRSpec.configure do |config|\n  config.openapi_no_additional_properties = true # default false\nend\n```\n\nYou can set similarly the option per individual example as shown in Strict (deprecated) sections.\n\n```ruby\n      response '200', 'blog found', :openapi_no_additional_properties do\n```\n```ruby\n      response '200', 'blog found', openapi_no_additional_properties: true do\n```\n\n#### All required properties\nIf you want to disallow missing required properties in response body, you can set the `openapi_all_properties_required` option to true:\n**Important** it will allow the additional properties\n\n```ruby\n# spec\u002Fswagger_helper.rb\nRSpec.configure do |config|\n  config.openapi_all_properties_required = true # default false\nend\n```\n\nYou can set similarly the option per individual example as shown in Strict (deprecated) sections.\n\n```ruby\n      response '200', 'blog found', :openapi_all_properties_required do\n```\n```ruby\n      response '200', 'blog found', openapi_all_properties_required: true do\n```\n\n### Null Values ###\n\nThis library is currently using JSON::Draft4 for validation of response models. Nullable properties can be supported with the non-standard property 'x-nullable' to a definition to allow null\u002Fnil values to pass. Or you can add the new standard ```nullable``` property to a definition.\n```ruby\ndescribe 'Blogs API' do\n  path '\u002Fblogs' do\n    post 'Creates a blog' do\n      ...\n\n      response '200', 'blog found' do\n        schema type: :object,\n          properties: {\n            id: { type: :integer },\n            title: { type: :string, nullable: true }, # preferred syntax\n            content: { type: :string, 'x-nullable': true } # legacy syntax, but still works\n          }\n        ....\n      end\n    end\n  end\nend\n```\n\n### Support for oneOf, anyOf or AllOf schemas ###\n\nOpenAPI 3.0 supports more flexible schema validation with the ```oneOf```, ```anyOf``` and ```allOf``` directives. rswag will handle these definitions and validate them properly.\n\n\nNotice the ```schema``` inside the ```response``` section. Placing a ```schema``` method inside the response will validate (and fail the tests)\nif during the integration test run the endpoint response does not match the response schema. This test validation can handle anyOf and allOf as well. See below:\n\n```ruby\n\n  path '\u002Fblogs\u002Fflexible' do\n    post 'Creates a blog flexible body' do\n      tags 'Blogs'\n      description 'Creates a flexible blog from provided data'\n      operationId 'createFlexibleBlog'\n      consumes 'application\u002Fjson'\n      produces 'application\u002Fjson'\n\n      parameter name: 'blog', in: :body, schema: {\n          oneOf: [\n            { '$ref' => '#\u002Fcomponents\u002Fschemas\u002Fblog' },\n            { '$ref' => '#\u002Fcomponents\u002Fschemas\u002Fflexible_blog' }\n          ]\n        }\n\n      response '201', 'flexible blog created' do\n        schema oneOf: [{ '$ref' => '#\u002Fcomponents\u002Fschemas\u002Fblog' }, { '$ref' => '#\u002Fcomponents\u002Fschemas\u002Fflexible_blog' }]\n        run_test!\n      end\n    end\n  end\n\n```\nThis automatic schema validation is a powerful feature of rswag.\n\n### Global Metadata ###\n\nIn addition to paths, operations and responses, OpenAPI also supports global API metadata. When you install rswag, a file called _openapi_helper.rb_ is added to your spec folder. This is where you define one or more OpenAPI documents and provide global metadata. Again, the format is based on OpenAPI so most of the global fields supported by the top level [\"Swagger\" object](http:\u002F\u002Fswagger.io\u002Fspecification\u002F#swaggerObject) can be provided with each document definition. As an example, you could define an OpenAPI document for each version of your API and in each case specify a title, version string.\n\n```ruby\n# spec\u002Fopenapi_helper.rb\nRSpec.configure do |config|\n  config.openapi_root = Rails.root.to_s + '\u002Fopenapi'\n\n  config.openapi_specs = {\n    'v1\u002Fopenapi.json' => {\n      openapi: '3.0.1',\n      info: {\n        title: 'API V1',\n        version: 'v1',\n        description: 'This is the first version of my API'\n      },\n      servers: [\n        {\n          url: 'https:\u002F\u002F{defaultHost}',\n          variables: {\n            defaultHost: {\n                default: 'www.example.com'\n            }\n          }\n        }\n      ]\n    },\n\n    'v2\u002Fopenapi.yaml' => {\n      openapi: '3.0.1',\n      info: {\n        title: 'API V2',\n        version: 'v2',\n        description: 'This is the second version of my API'\n      },\n      servers: [\n        {\n          url: '{protocol}:\u002F\u002F{defaultHost}',\n          variables: {\n            protocol: {\n              default: :https\n            },\n            defaultHost: {\n                default: 'www.example.com'\n            }\n          }\n        }\n      ]\n    }\n  }\nend\n```\n\n#### Supporting multiple versions of API ####\nBy default, the paths, operations and responses defined in your spec files will be associated with the first OpenAPI document in _openapi_helper.rb_. If your API has multiple versions, you should be using separate documents to describe each of them. In order to assign a file with a given version of API, you'll need to add the ```openapi_spec``` tag to each spec specifying its target document name:\n\n```ruby\n# spec\u002Frequests\u002Fv2\u002Fblogs_spec.rb\ndescribe 'Blogs API', openapi_spec: 'v2\u002Fopenapi.yaml' do\n\n  path '\u002Fblogs' do\n  ...\n\n  path '\u002Fblogs\u002F{id}' do\n  ...\nend\n```\n\n#### Supporting YAML format ####\n\nBy default, the OpenAPI specs are generated in JSON format. If you want to generate them in YAML format, you can specify the OpenAPI format in the `openapi_helper.rb` file:\n\n```ruby\n# spec\u002Fopenapi_helper.rb\nRSpec.configure do |config|\n  config.openapi_root = Rails.root.to_s + '\u002Fopenapi'\n\n  # Use if you want to see which test is running\n  # config.formatter = :documentation\n\n  # Generate OpenAPI docs in YAML format\n  config.openapi_format = :yaml\n\n  config.openapi_specs = {\n    'v1\u002Fopenapi.yaml' => {\n      openapi: '3.0.1',\n      info: {\n        title: 'API V1',\n        version: 'v1',\n        description: 'This is the first version of my API'\n      },\n      servers: [\n        {\n          url: 'https:\u002F\u002F{defaultHost}',\n          variables: {\n            defaultHost: {\n                default: 'www.example.com'\n            }\n          }\n        }\n      ]\n    },\n  }\nend\n```\n\n#### Formatting the description literals: ####\nOpenAPI supports the Markdown syntax to format strings. This can be especially handy if you were to provide a long description of a given API version or endpoint. Use [this guide](https:\u002F\u002Fgithub.com\u002Fadam-p\u002Fmarkdown-here\u002Fwiki\u002FMarkdown-Cheatsheet) for reference.\n\n__NOTE:__ There is one difference between the official Markdown syntax and OpenAPI interpretation, namely tables. To create a table like this:\n\n| Column1 | Column2 |\n| ------- | ------- |\n| cell1   | cell2   |\n\nyou should use the following syntax, making sure there is no whitespace at the start of any of the lines:\n\n```\n&#13;\n| Column1 | Column2 | &#13; |\n| ------- | ------- |&#13;\n| cell1   | cell2    |&#13;\n&#13;\n```\n\n### Specifying\u002FTesting API Security ###\n\nOpenAPI allows for the specification of different security schemes and their applicability to operations in an API.\nTo leverage this in rswag, you define the schemes globally in _openapi_helper.rb_ and then use the \"security\" attribute at the operation level to specify which schemes, if any, are applicable to that operation.\nOpenAPI supports :basic, :bearer, :apiKey and :oauth2 and :openIdConnect scheme types. See [the spec](https:\u002F\u002Fswagger.io\u002Fdocs\u002Fspecification\u002Fauthentication\u002F) for more info.\n\n```ruby\n# spec\u002Fopenapi_helper.rb\nRSpec.configure do |config|\n  config.openapi_root = Rails.root.to_s + '\u002Fopenapi'\n\n  config.openapi_specs = {\n    'v1\u002Fopenapi.json' => {\n      ...  # note the new Open API 3.0 compliant security structure here, under \"components\"\n      components: {\n        securitySchemes: {\n          basic_auth: {\n            type: :http,\n            scheme: :basic\n          },\n          api_key: {\n            type: :apiKey,\n            name: 'api_key',\n            in: :header\n          }\n        }\n      }\n    }\n  }\nend\n\n# spec\u002Frequests\u002Fblogs_spec.rb\ndescribe 'Blogs API' do\n\n  path '\u002Fblogs' do\n\n    post 'Creates a blog' do\n      tags 'Blogs'\n      security [ basic_auth: [] ]\n      ...\n\n      response '201', 'blog created' do\n        let(:request_headers) { { 'Authorization' => \"Basic #{::Base64.strict_encode64('jsmith:jspass')}\" } }\n        run_test!\n      end\n\n      response '401', 'authentication failed' do\n        let(:request_headers) { { 'Authorization' => \"Basic #{::Base64.strict_encode64('bogus:bogus')}\" } }\n        run_test!\n      end\n    end\n  end\nend\n\n# example of documenting an endpoint that handles basic auth and api key based security\ndescribe 'Auth examples API' do\n  path '\u002Fauth-tests\u002Fbasic-and-api-key' do\n    post 'Authenticates with basic auth and api key' do\n      tags 'Auth Tests'\n      operationId 'testBasicAndApiKey'\n      security [{ basic_auth: [], api_key: [] }]\n\n      response '204', 'Valid credentials' do\n        let(:request_headers) {\n          {\n            'Authorization' => \"Basic #{::Base64.strict_encode64('jsmith:jspass')}\"\n            'api_key' => 'foobar',\n          }\n        }\n        run_test!\n      end\n\n      response '401', 'Invalid credentials' do\n        let(:request_headers) {\n          {\n            'Authorization' => \"Basic #{::Base64.strict_encode64('jsmith:jspass')}\"\n            'api_key' => 'bar-foo',\n          }\n        }\n        run_test!\n      end\n    end\n  end\nend\n\n\n```\n\n__NOTE:__ Depending on the scheme types, you'll be required to assign a corresponding parameter value with each example.\nFor example, :basic auth is required above and so the :Authorization (header) parameter must be set accordingly\n\n## Configuration & Customization ##\n\nThe steps described above will get you up and running with minimal setup. However, rswag offers a lot of flexibility to customize as you see fit. Before exploring the various options, you'll need to be aware of its different components. The following table lists each of them and the files that get added\u002Fupdated as part of a standard install.\n\n| Gem             | Description                                                                                                                  | Added\u002FUpdated                                        |\n| --------------- | ---------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- |\n| __rswag-specs__ | Swagger-based DSL for rspec & accompanying rake task for generating OpenAPI files                                            | _spec\u002Fopenapi_helper.rb_                             |\n| __rswag-api__   | Rails Engine that exposes your OpenAPI files as JSON endpoints                                                               | _config\u002Finitializers\u002Frswag_api.rb, config\u002Froutes.rb_ |\n| __rswag-ui__    | Rails Engine that includes [swagger-ui](https:\u002F\u002Fgithub.com\u002Fswagger-api\u002Fswagger-ui) and powers it from your Swagger endpoints | _config\u002Finitializers\u002Frswag_ui.rb, config\u002Froutes.rb_  |\n\n### Output Location for Generated OpenAPI Files ###\n\nYou can adjust this in the _openapi_helper.rb_ that's installed with __rswag-specs__:\n\n```ruby\n# spec\u002Fopenapi_helper.rb\nRSpec.configure do |config|\n  config.openapi_root = Rails.root.to_s + '\u002Fyour-custom-folder-name'\n  ...\nend\n```\n\n__NOTE__: If you do change this, you'll also need to update the rswag_api.rb initializer (assuming you're using rswag-api). More on this later.\n\n### Input Location for Rspec Tests ###\n\nBy default, rswag will search for integration tests in _spec\u002Frequests_, _spec\u002Fapi_ and _spec\u002Fintegration_. If you want to use tests from other locations, provide the PATTERN argument to rake:\n\n```ruby\n# search for tests in spec\u002Fopenapi\nrake rswag:specs:swaggerize PATTERN=\"spec\u002Fopenapi\u002F**\u002F*_spec.rb\"\n```\n\n### Additional rspec options\n\nYou can add additional rspec parameters using the ADDITIONAL_RSPEC_OPTS env variable:\n\n```ruby\n# Only include tests tagged \"rswag\"\nrake rswag:specs:swaggerize ADDITIONAL_RSPEC_OPTS=\"--tag rswag\"\n```\n\n### Referenced Parameters and Schema Definitions ###\n\nOpenAPI allows you to describe JSON structures inline with your operation descriptions OR as referenced globals.\nFor example, you might have a standard response structure for all failed operations.\nRather than repeating the schema in every operation spec, you can define it globally and provide a reference to it in each spec:\n\n```ruby\n# spec\u002Fopenapi_helper.rb\nconfig.openapi_specs = {\n  'v1\u002Fopenapi.json' => {\n    openapi: '3.0.0',\n    info: {\n      title: 'API V1'\n    },\n    components: {\n      schemas: {\n        errors_object: {\n          type: 'object',\n          properties: {\n            errors: { '$ref' => '#\u002Fcomponents\u002Fschemas\u002Ferrors_map' }\n          }\n        },\n        errors_map: {\n          type: 'object',\n          additionalProperties: {\n            type: 'array',\n            items: { type: 'string' }\n          }\n        },\n        blog: {\n          type: 'object',\n          properties: {\n            id: { type: 'integer' },\n            title: { type: 'string' },\n            content: { type: 'string', nullable: true },\n            thumbnail: { type: 'string', nullable: true }\n          },\n          required: %w[id title]\n        },\n        new_blog: {\n          type: 'object',\n          properties: {\n            title: { type: 'string' },\n            content: { type: 'string', nullable: true },\n            thumbnail: { type: 'string', format: 'binary', nullable: true }\n          },\n          required: %w[title]\n        }\n      }\n    }\n  }\n}\n\n# spec\u002Frequests\u002Fblogs_spec.rb\ndescribe 'Blogs API' do\n\n  path '\u002Fblogs' do\n\n    post 'Creates a blog' do\n\n      parameter name: 'new_blog', in: :body, schema: { '$ref' => '#\u002Fcomponents\u002Fschemas\u002Fnew_blog' }\n\n      response 422, 'invalid request' do\n        schema '$ref' => '#\u002Fcomponents\u002Fschemas\u002Ferrors_object'\n  ...\nend\n\n# spec\u002Frequests\u002Fcomments_spec.rb\ndescribe 'Blogs API' do\n\n  path '\u002Fblogs\u002F{blog_id}\u002Fcomments' do\n\n    post 'Creates a comment' do\n\n      response 422, 'invalid request' do\n        schema '$ref' => '#\u002Fcomponents\u002Fschemas\u002Ferrors_object'\n  ...\nend\n```\n\n### Request examples ###\n\n```ruby\n# spec\u002Fintegration\u002Fblogs_spec.rb\ndescribe 'Blogs API' do\n\n  path '\u002Fblogs\u002F{blog_id}' do\n\n    get 'Retrieves a blog' do\n\n      request_body_example value: { some_field: 'Foo' }, name: 'request_example_1', summary: 'A request example'\n\n      response 200, 'blog found' do\n        ...\n```\n\nto use the actual request from the spec as the example:\n\n```ruby\nconfig.after(:each, operation: true, use_as_request_example: true) do |spec|\n  spec.metadata[:operation][:request_examples] ||= []\n\n  example = {\n    value: JSON.parse(request.body.string, symbolize_names: true),\n    name: 'request_example_1',\n    summary: 'A request example'\n  }\n\n  spec.metadata[:operation][:request_examples] \u003C\u003C example\nend\n```\n\n### Response headers ###\n\nIn Rswag, you could use `header` method inside the response block to specify header objects for this response.\nRswag will validate your response headers with those header objects and inject them into the generated OpenAPI spec:\n\n```ruby\n# spec\u002Frequests\u002Fcomments_spec.rb\ndescribe 'Blogs API' do\n\n  path '\u002Fblogs\u002F{blog_id}\u002Fcomments' do\n\n    post 'Creates a comment' do\n\n      response 422, 'invalid request' do\n        header 'X-Rate-Limit-Limit', schema: { type: :integer }, description: 'The number of allowed requests in the current period'\n        header 'X-Rate-Limit-Remaining', schema: { type: :integer }, description: 'The number of remaining requests in the current period'\n  ...\nend\n```\n\n#### Nullable or Optional Response Headers ####\n\nYou can include `nullable` or `required` to specify whether a response header must be present or may be null. When `nullable` is not included, the headers validation validates that the header response is non-null. When `required` is not included, the headers validation validates the the header response is passed.\n\n```ruby\n# spec\u002Fintegration\u002Fcomments_spec.rb\ndescribe 'Blogs API' do\n\n  path '\u002Fblogs\u002F{blog_id}\u002Fcomments' do\n\n    get 'Gets a list of comments' do\n\n      response 200, 'blog found' do\n        header 'X-Cursor', schema: { type: :string, nullable: true }, description: 'The cursor to get the next page of comments.'\n        header 'X-Per-Page', schema: { type: :integer }, required: false, description: 'The number of comments per page.'\n  ...\nend\n```\n\n### Response examples ###\n\nYou can provide custom response examples to the generated OpenAPI spec by calling the method `examples` inside the response block:\nHowever, auto generated example responses are now enabled by default in rswag. See below.\n\n```ruby\n# spec\u002Frequests\u002Fblogs_spec.rb\ndescribe 'Blogs API' do\n\n  path '\u002Fblogs\u002F{blog_id}' do\n\n    get 'Retrieves a blog' do\n\n      response 200, 'blog found' do\n        example 'application\u002Fjson', :example_key, {\n            id: 1,\n            title: 'Hello world!',\n            content: '...'\n          }\n        example 'application\u002Fjson', :example_key_2, {\n            id: 1,\n            title: 'Hello world!',\n            content: '...'\n          }, \"Summary of the example\", \"Longer description of the example\"\n  ...\nend\n```\n\n\n### Enable auto generation examples from responses ###\n\n\nTo enable examples generation from responses add callback above run_test! like:\n\n```ruby\nafter do |example|\n  content = example.metadata[:response][:content] || {}\n  example_spec = {\n    \"application\u002Fjson\"=>{\n      examples: {\n        test_example: {\n          value: JSON.parse(response.body, symbolize_names: true)\n        }\n      }\n    }\n  }\n  example.metadata[:response][:content] = content.deep_merge(example_spec)\nend\n```\n\nNote you will need to disable the `--dry-run` option for Rspec 3.0.0 or higher to\nrun the after callback. See below for more information.\n\n#### Dry Run Option ####\n\nThe `--dry-run` option is enabled by default for Rspec 3, but if you need to\ndisable it you can use the environment variable `RSWAG_DRY_RUN=0` during the\ngeneration command or add the following to your `config\u002Fenvironments\u002Ftest.rb`:\n\n```ruby\nRSpec.configure do |config|\n  config.rswag_dry_run = false\nend\n```\n\n#### Running tests without documenting ####\n\nIf you want to use Rswag for testing without adding it to you OpenAPI specs, you can provide the document tag:\n```ruby\ndescribe 'Blogs API' do\n  path '\u002Fblogs\u002F{blog_id}' do\n    get 'Retrieves a blog' do\n      # documentation is now disabled for this response only\n      response 200, 'blog found', document: false do\n        ...\n```\n\nYou can also reenable documentation for specific responses only:\n```ruby\n# documentation is now disabled\ndescribe 'Blogs API', document: false do\n  path '\u002Fblogs\u002F{blog_id}' do\n    get 'Retrieves a blog' do\n      # documentation is reenabled for this response only\n      response 200, 'blog found', document: true do\n        ...\n      end\n\n      response 401, 'special case' do\n        ...\n      end\n```\n\n##### rswag helper methods #####\n\u003C!--\nThere are some helper methods to help with documenting request bodies.\n```ruby\ndescribe 'Blogs API', type: :request, openapi_spec: 'v1\u002Fopenapi.json' do\n  let(:request_headers) { { 'api_key' => 'fake_key' } }\n\n  path '\u002Fblogs' do\n    post 'Creates a blog' do\n      tags 'Blogs'\n      description 'Creates a new blog from provided data'\n      operationId 'createBlog'\n      consumes 'application\u002Fjson'\n      produces 'application\u002Fjson'\n\n      request_body_json schema: { '$ref' => '#\u002Fcomponents\u002Fschemas\u002Fblog' },\n                        examples: :blog\n\n      request_body_text_plain\n      request_body_xml schema: { '$ref' => '#\u002Fcomponents\u002Fschemas\u002Fblog' }\n\n      let(:blog) { { blog: { title: 'foo', content: 'bar' } } }\n\n      response '201', 'blog created' do\n        schema '$ref' => '#\u002Fcomponents\u002Fschemas\u002Fblog'\n        run_test!\n      end\n\n      response '422', 'invalid request' do\n        schema '$ref' => '#\u002Fcomponents\u002Fschemas\u002Ferrors_object'\n        let(:blog) { { blog: { title: 'foo' } } }\n\n        run_test! do |response|\n          expect(response.body).to include(\"can't be blank\")\n        end\n      end\n    end\n  end\nend\n```\n\nIn the above example, we see methods ```request_body_json``` ```request_body_plain``` ```request_body_xml```.\nThese methods can be used to describe json, plain text and xml body. They are just wrapper methods to setup posting JSON, plain text or xml into your endpoint.\nThe simplest most common usage is for json formatted body to use the schema: to specify the location of the schema for the request body\nand the examples: :blog which will create a named example \"blog\" under the \"requestBody \u002F content \u002F application\u002Fjson \u002F examples\" section.\nAgain, documenting request response examples changed in OpenAPI 3.0. The example above would generate a openapi.json snippet that looks like this:\n\n```json\n        ...\n        {\"requestBody\": {\n          \"required\": true,\n          \"content\": {\n            \"application\u002Fjson\": {\n              \"examples\": {\n                \"blog\": {  \u002F\u002F takes the name from  examples: :blog above\n                  \"value\": {  \u002F\u002F this is OpenAPI 3.0 structure -> https:\u002F\u002Fswagger.io\u002Fdocs\u002Fspecification\u002Fadding-examples\u002F\n                    \"blog\": { \u002F\u002F here is the actual JSON payload that is submitted to the service, and shows up in swagger UI as an example\n                      \"title\": \"foo\",\n                      \"content\": \"bar\"\n                    }\n                  }\n                }\n              },\n              \"schema\": {\n                \"$ref\": \"#\u002Fcomponents\u002Fschemas\u002Fblog\"\n              }\n            },\n            \"test\u002Fplain\": {\n              \"schema\": {\n                \"type\": \"string\"\n              }\n            },\n            \"application\u002Fxml\": {\n              \"schema\": {\n                \"$ref\": \"#\u002Fcomponents\u002Fschemas\u002Fblog\"\n              }\n            }\n          }\n        },\n        }\n```\n\n*NOTE:* for this example request body to work in the tests properly, you need to ``let`` a variable named *blog*.\nThe variable with the matching name (blog in this case) is eval-ed and captured to be placed in the examples section.\nThis ```let``` value is used in the integration test to run the test AND captured and injected into the requestBody section.\n\n##### rswag response examples #####\n\nIn the same way that requestBody examples can be captured and injected into the output, response examples can also be captured.\nUsing the above example, when the integration test is run - the OpenAPI spec would include the following snippet providing more useful real world examples\ncapturing the response from the execution of the integration test.\n\n```json\n       ...  \"responses\": {\n          \"201\": {\n            \"description\": \"blog created\",\n            \"content\": {\n              \"application\u002Fjson\": {\n                \"example\": {\n                  \"id\": 1,\n                  \"title\": \"foo\",\n                  \"content\": \"bar\",\n                  \"thumbnail\": null\n                },\n                \"schema\": {\n                  \"$ref\": \"#\u002Fcomponents\u002Fschemas\u002Fblog\"\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"invalid request\",\n            \"content\": {\n              \"application\u002Fjson\": {\n                \"example\": {\n                  \"errors\": {\n                    \"content\": [\n                      \"can't be blank\"\n                    ]\n                  }\n                },\n                \"schema\": {\n                  \"$ref\": \"#\u002Fcomponents\u002Fschemas\u002Ferrors_object\"\n                }\n              }\n            }\n          }\n        }\n```\n -->\n### Route Prefix for OpenAPI JSON Endpoints ###\n\nThe functionality to expose OpenAPI files, such as those generated by rswag-specs, as JSON endpoints is implemented as a Rails Engine. As with any Engine, you can change its mount prefix in _routes.rb_:\n\n```ruby\nTestApp::Application.routes.draw do\n  ...\n\n  mount Rswag::Api::Engine => 'your-custom-prefix'\nend\n```\n\nAssuming a OpenAPI file exists at &lt;openapi_root&gt;\u002Fv1\u002Fopenapi.json, this configuration would expose the file as the following JSON endpoint:\n\n```\nGET http:\u002F\u002F\u003Chostname>\u002Fyour-custom-prefix\u002Fv1\u002Fopenapi.json\n```\n\n### Root Location for OpenAPI Files ###\n\nYou can adjust this in the _rswag_api.rb_ initializer that's installed with __rspec-api__:\n\n```ruby\nRswag::Api.configure do |c|\n  c.openapi_root = Rails.root.to_s + '\u002Fyour-custom-folder-name'\n  ...\nend\n```\n\n__NOTE__: If you're using rswag-specs to generate OpenAPI files, you'll want to ensure they both use the same &lt;openapi_root&gt;. The reason for separate settings is to maintain independence between the two gems. For example, you could install rswag-api independently and create your OpenAPI files manually.\n\n### Dynamic Values for OpenAPI JSON ##\n\nThere may be cases where you need to add dynamic values to the OpenAPI JSON that's returned by rswag-api. For example, you may want to provide an explicit host name. Rather than hardcoding it, you can configure a filter that's executed prior to serializing every OpenAPI document:\n\n```ruby\nRswag::Api.configure do |c|\n  ...\n\n  c.openapi_filter = lambda { |openapi, env| openapi['host'] = env['HTTP_HOST'] }\nend\n```\n\nNote how the filter is passed the rack env for the current request. This provides a lot of flexibility. For example, you can assign the \"host\" property (as shown) or you could inspect session information or an Authorization header and remove operations based on user permissions.\n\n### Custom Headers for OpenAPI Files ###\n\nYou can specify custom headers for serving your generated OpenAPI JSON. For example you may want to force a specific charset for the 'Content-Type' header. You can configure a hash of headers to be sent with the request:\n\n```ruby\nRswag::Api.configure do |c|\n  ...\n\n  c.openapi_headers = { 'Content-Type' => 'application\u002Fjson; charset=UTF-8' }\nend\n```\n\nTake care when overriding Content-Type if you serve both YAML and JSON files as it will no longer switch the Content-Type header correctly.\n\n\n### Enable Swagger Endpoints for swagger-ui ###\n\nYou can update the _rswag_ui.rb_ initializer, installed with rswag-ui, to specify which Swagger endpoints should be available to power the documentation UI. If you're using rswag-api, these should correspond to the Swagger endpoints it exposes. When the UI is rendered, you'll see these listed in a drop-down to the top right of the page:\n\n```ruby\nRswag::Ui.configure do |c|\n  c.openapi_endpoint '\u002Fapi-docs\u002Fv1\u002Fopenapi.json', 'API V1 Docs'\n  c.openapi_endpoint '\u002Fapi-docs\u002Fv2\u002Fopenapi.json', 'API V2 Docs'\nend\n```\n\n### Enable Simple Basic Auth for swagger-ui\n\nYou can also update the _rswag_ui.rb_ initializer, installed with rswag-ui to specify a username and password should you want to keep your documentation private.\n\n```ruby\nRswag::Ui.configure do |c|\n  c.basic_auth_enabled = true\n  c.basic_auth_credentials 'username', 'password'\nend\n```\n\n### Route Prefix for the swagger-ui ###\n\nSimilar to rswag-api, you can customize the swagger-ui path by changing its mount prefix in _routes.rb_:\n\n```ruby\nTestApp::Application.routes.draw do\n  ...\n\n  mount Rswag::Api::Engine => 'api-docs'\n  mount Rswag::Ui::Engine => 'your-custom-prefix'\nend\n```\n\n### Customizing the swagger-ui ###\n\nThe swagger-ui provides several options for customizing its behavior, all of which are documented here https:\u002F\u002Fgithub.com\u002Fswagger-api\u002Fswagger-ui\u002Ftree\u002F2.x#swaggerui. If you need to tweak these or customize the overall look and feel of your swagger-ui, then you'll need to provide your own version of index.html. You can do this with the following generator.\n\n```ruby\nrails g rswag:ui:custom\n\n```\n\nThis will add a local version that you can modify at _app\u002Fviews\u002Frswag\u002Fui\u002Fhome\u002Findex.html.erb_. For example, it will let you to add your own `\u003Ctitle>` and favicon.\n\nTo replace the *\"Swagger sponsored by\"* brand image, you can add the following script to the generated file:\n\n```html\n\u003Cscript>\n  (function () {\n  window.addEventListener(\"load\", function () {\n      setTimeout(function () {\n\n          var logo = document.getElementsByClassName('link');\n\n          logo[0].children[0].alt = \"My API\";\n          logo[0].children[0].src = \"\u002Ffavicon.png\";\n      });\n  }); })();\n\u003C\u002Fscript>\n```\n\nThe above script would expect to find an image named `favicon.png` in the public folder.\n\nYou can also customize the swagger ui with _configuration objects._ Rswag's `config_object` can be used with swagger's configuration parameters found here: https:\u002F\u002Fswagger.io\u002Fdocs\u002Fopen-source-tools\u002Fswagger-ui\u002Fusage\u002Fconfiguration\u002F\nThe ui can be configured in the _config\u002Finitializers\u002Frswag-ui.rb_ file like so:\n\n```ruby\nRswag::Ui.configure do |c|\n  c.config_object['defaultModelsExpandDepth'] = 1\nend\n\n```\n\n### Serve UI Assets Directly from your Web Server\n\nRswag ships with an embedded version of the [swagger-ui](https:\u002F\u002Fgithub.com\u002Fswagger-api\u002Fswagger-ui), which is a static collection of JavaScript and CSS files. These assets are served by the rswag-ui middleware. However, for optimal performance you may want to serve them directly from your web server (e.g. Apache or NGINX). To do this, you'll need to copy them to the web server root. This is the \"public\" folder in a typical Rails application.\n\n```\nbundle exec rake rswag:ui:copy_assets[public\u002Fapi-docs]\n```\n\n__NOTE:__: The provided subfolder MUST correspond to the UI mount prefix - \"api-docs\" by default.\n\n\nNotes to test OpenAPI output locally with Swagger editor\n```\ndocker pull swaggerapi\u002Fswagger-editor\n```\n```\ndocker run -d -p 80:8080 swaggerapi\u002Fswagger-editor\n```\nThis will run the swagger editor in the docker daemon and can be accessed\nat ```http:\u002F\u002Flocalhost```. From here, you can use the UI to load the generated openapi.json to validate the output.\n\n### Linting with RuboCop RSpec\n\nWhen you lint your RSpec spec files with `rubocop-rspec`, it will fail to detect RSpec aliases that Rswag defines.\nMake sure to use `rubocop-rspec` 2.0 or newer and add the following to your `.rubocop.yml`:\n\n```yaml\ninherit_gem:\n  rswag-specs: .rubocop_rspec_alias_config.yml\n```\n","rswag 是一个为基于 Rails 的 API 无缝添加 Swagger 文档的工具。它通过扩展 rspec-rails 的“请求规格”功能，使用一种简洁直观的 DSL 来描述和测试 API 操作，并能自动生成 OpenAPI 文件（支持 OpenAPI 3.0），这些文件可以以 YAML 或 JSON 格式提供。此外，rswag 还集成了 swagger-ui，使得开发者可以直接从集成测试生成美观且交互式的 API 文档。此项目非常适合需要快速生成并维护 API 文档、同时希望保持测试覆盖率的 Ruby on Rails 开发者使用。",2,"2026-06-11 03:15:38","top_language"]