Rswag Documentation

repository·master·Indexed 24 days ago

https://github.com/rswag/rswag

A toolchain for Rails APIs that extends rspec-rails request specs with a Swagger-based DSL. Rswag allows developers to write integration tests that serve as living OpenAPI 3.0 documentation with an embedded Swagger UI. It consists of three main components: rswag-specs for the DSL and file generation, rswag-api for exposing OpenAPI JSON endpoints, and rswag-ui for providing the Swagger UI interface.

Tokens
9K
Snippets
26
Records
62
Agent score
78%

What's inside Rswag

  1. Understand the Rswag component architecture

    master

    Rswag is composed of three main gems that work together to manage the OpenAPI lifecycle:

    GemDescriptionFiles Added/Updated
    rswag-specsProvides the Swagger-based DSL for RSpec and a Rake task to generate OpenAPI files.spec/openapi_helper.rb
    rswag-apiA Rails Engine that exposes your generated OpenAPI files as JSON endpoints.config/initializers/rswag_api.rb, config/routes.rb
    rswag-uiA Rails Engine that includes Swagger UI and powers it using your Swagger endpoints.config/initializers/rswag_ui.rb, config/routes.rb
  2. Use the Rswag DSL to describe and test API operations

    master

    Rswag extends rspec-rails request specs with a DSL for defining OpenAPI 3.0 compatible documentation and running tests simultaneously.

    Key DSL components include:

    • path: Defines the endpoint path.
    • post/get/etc.: Defines the HTTP method and operation description.
    • tags: Assigns tags for grouping in Swagger UI.
    • consumes/produces: Specifies media types.
    • parameter: Defines parameters (in body, path, query, etc.).
    • response: Defines the expected response status and schema.
    • run_test!: Executes the actual integration test for the described operation.
    • let(:request_params): Sets the parameters used by run_test!.
    • let(:request_headers): Sets headers used by run_test!.
    # spec/requests/blogs_spec.rb
    require 'openapi_helper'
    
    describe 'Blogs API' do
      path '/blogs' do
        post 'Creates a blog' do
          tags 'Blogs'
          consumes 'application/json'
          parameter name: 'blog', in: :body, schema: {
            type: :object,
            properties: {
              title: { type: :string },
              content: { type: :string }
            },
            required: [ 'title', 'content' ]
          }
    
          response '201', 'blog created' do
            let(:request_params) { { 'blog' => { title: 'foo', content: 'bar' } } }
            run_test!
          end
    
          response '422', 'invalid request' do
            let(:request_params) { { 'blog' => { title: 'foo' } } }
            run_test!
          end
        end
      end
    
      path '/blogs/{id}' do
        get 'Retrieves a blog' do
          tags 'Blogs', 'Another Tag'
          produces 'application/json', 'application/xml'
          parameter name: 'id', in: :path, type: :string
          request_body_example value: { some_field: 'Foo' }, name: 'basic', summary: 'Request example description'
    
          response '200', 'blog found' do
            schema type: :object,
              properties: {
                id: { type: :integer },
                title: { type: :string },
                content: { type: :string }
              },
              required: [ 'id', 'title', 'content' ]
    
            let(:request_params) { 'id' => { Blog.create(title: 'foo', content: 'bar').id } }
            run_test!
          end
    
          response '404', 'blog not found' do
            let(:request_params) { { 'id' => 'invalid' } }
            run_test!
          end
    
          response '406', 'unsupported accept header' do
            let(:request_headers) { { 'Accept' => 'application/foo' } }
            run_test!
          end
        end
      end
    end
  3. Define global OpenAPI schemas and references

    master

    Instead of defining JSON structures inline for every operation, you can define them globally in spec/openapi_helper.rb under config.openapi_specs. You can then reference these schemas in your request specs using the '$ref' key.

    # spec/openapi_helper.rb
    config.openapi_specs = {
      'v1/openapi.json' => {
        openapi: '3.0.0',
        info: { title: 'API V1' },
        components: {
          schemas: {
            errors_object: {
              type: 'object',
              properties: {
                errors: { '$ref' => '#/components/schemas/errors_map' }
              }
            },
            # ... other schemas
          }
        }
      }
    }
    
    # spec/requests/blogs_spec.rb
    post 'Creates a blog' do
      parameter name: 'new_blog', in: :body, schema: { '$ref' => '#/components/schemas/new_blog' }
      response 422, 'invalid request' do
        schema '$ref' => '#/components/schemas/errors_object'
      end
    end
  4. Generate an API integration spec

    master

    You can use the Rswag generator to create a new integration spec for a controller. This creates a template using the Rswag DSL to describe and test your API operations.

    By default, specs are created in the spec/requests folder. You can customize the destination folder using the --spec_path option.

    Example command:

    rails generate rspec:swagger API::MyController

    Example with custom path:

    rails generate rspec:swagger API::BlogsController --spec_path integration
  5. Configure RuboCop RSpec to recognize Rswag aliases

    master

    To prevent rubocop-rspec from flagging Rswag's custom DSL aliases, inherit the Rswag configuration in your .rubocop.yml.

    # .rubocop.yml
    inherit_gem:
      rswag-specs: .rubocop_rspec_alias_config.yml
  6. Run Rswag installation generators

    master

    After adding the gems to your Gemfile, run the installation generators to set up the necessary configuration and files.

    If you installed the single rswag gem:

    rails g rswag:install

    If you installed the components separately:

    rails g rswag:api:install
    rails g rswag:ui:install
    RAILS_ENV=test rails g rswag:specs:install
  7. Assign specs to multiple API versions

    master

    By default, specs are associated with the first document in openapi_helper.rb. To target a specific versioned document, use the openapi_spec tag on your describe block.

    # spec/requests/v2/blogs_spec.rb
    describe 'Blogs API', openapi_spec: 'v2/openapi.yaml' do
      path '/blogs' do
        # ...
      end
    end
  8. Specify and test API Security schemes

    master

    To implement security in your documentation and tests:

    1. Define Schemes Globally: In openapi_helper.rb, add components: { securitySchemes: { ... } } to your spec definition. Supported types include :http (with :basic or :bearer schemes), :apiKey, :oauth2, and :openIdConnect.
    2. Apply to Operations: Use the security method within an operation block to specify which schemes apply. You can pass an array of hashes to support multiple schemes (e.g., security [{ basic_auth: [], api_key: [] }]).
    3. Test with Headers: In your response blocks, use let(:request_headers) to provide the necessary credentials (like Authorization headers) for the test to pass.
    # spec/openapi_helper.rb
    config.openapi_specs = {
      'v1/openapi.json' => {
        components: {
          securitySchemes: {
            basic_auth: { type: :http, scheme: :basic },
            api_key: { type: :apiKey, name: 'api_key', in: :header }
          }
        }
      }
    }
    
    # spec/requests/blogs_spec.rb
    path '/blogs' do
      post 'Creates a blog' do
        security [ basic_auth: [] ]
    
        response '201', 'blog created' do
          let(:request_headers) { { 'Authorization' => "Basic #{::Base64.strict_encode64('jsmith:jspass')}" } }
          run_test!
        end
      end
    end
  9. Generate OpenAPI JSON files from specs

    master

    Once your integration tests are written and passing, you can generate the OpenAPI JSON files using a rake task. This task reads your Rswag specs and produces the documentation files used by Swagger UI.

    If you installed the single rswag gem:

    rake rswag:specs:swaggerize

    (Note: rake rswag is an alias for this command)

    If you installed the components separately:

    RAILS_ENV=test rails rswag
  10. Install Rswag

    master

    To add Rswag to your Rails application, add the rswag gem to your Gemfile.

    If you prefer to manage the components separately to avoid loading rspec in all environments, you can install rswag-api, rswag-ui, and rswag-specs individually.

    Note: If you do not add the gems to the :development group, you must prefix generators and rake tasks with RAILS_ENV=test.

    # Option 1: Single gem
    gem 'rswag'
    
    # Option 2: Separate components
    gem 'rswag-api'
    gem 'rswag-ui'
    
    group :development, :test do
      gem 'rspec-rails'
      gem 'rswag-specs'
    end
  11. Customize the Swagger UI appearance

    master

    To customize the look and feel (like title or favicon), generate a custom UI template using the Rswag generator. This creates a local version of index.html.erb in your app.

    rails g rswag:ui:custom
  12. Use the rspec DSL to describe API paths, operations, and responses

    master

    Rswag uses an rspec-based DSL that mirrors the Swagger/OpenAPI specification. You define an API by specifying a path, followed by HTTP verbs (operations) like get or post. Path parameters should be enclosed in curly braces (e.g., /users/{id}).

    Inside an operation block, you can define parameters and responses. To actually execute the test and validate the response against your schema, you must call the run_test! method within a response block. Rswag uses the request_params rspec variable to build the request body or query parameters based on your descriptions.