
June 9, 2025
A structured exposition with illustrative examples
Abstract
Accurate, current, and machine-readable documentation is a prerequisite for reliable consumption of web APIs. While manual Swagger (OpenAPI) definitions quickly diverge from production behaviour, RSwag bridges this gap by synthesising documentation directly from integration tests written in RSpec. This article (i) situates RSwag within the Rails documentation landscape, (ii) details its installation and configuration, and (iii) demonstrates, through a worked example, the end-to-end generation of an OpenAPI specification and interactive Swagger UI.
🛠️ Improve or Create Your API Documentation
Whether you’re refining an existing API or starting fresh, integrating Swagger (OpenAPI) with RSwag in your Ruby on Rails project can dramatically improve clarity and developer experience.
📬 Get in Touch1 Introduction
The proliferation of service-oriented architectures has intensified the need for robust API contracts. OpenAPI—formerly Swagger (https://swagger.io/) —has emerged as a de-facto standard, yet authoring and maintaining specification files can be labour-intensive. RSwag addresses this maintenance burden by embedding an OpenAPI-aware, domain-specific language (DSL) directly into RSpec request examples. In so doing, test execution validates behaviour and simultaneously emits a complete specification, ensuring documentation fidelity with negligible additional effort.
2 Background and Related Work
Rails developers have traditionally relied on rspec-api, Apipie, or manual Markdown to disseminate endpoint semantics. These approaches either decouple documentation from test execution or restrict the expressiveness of the resulting artefacts. RSwag distinguishes itself by
- leveraging RSpec’s ubiquitous testing culture,
- embracing the full OpenAPI 3.0 feature set (components, oneOf/anyOf, security schemes, etc.), and
- bundling Swagger UI for interactive exploration of the generated specification.
3 Methodology

3.1 Gem Architecture
RSwag is decomposed into three gems:

This separation permits independent deployment of documentation assets (e.g. served statically by NGINX) and test-only dependencies.
3.2 Installation Procedure
# Gemfile
gem 'rswag-api'
gem 'rswag-ui'
group :development, :test do
gem 'rswag-specs'
gem 'rspec-rails' # if not already present
end
bundle install
rails g rswag:api:install # mounts /api-docs
rails g rswag:ui:install # copies Swagger UI assets
RAILS_ENV=test rails g rswag:specs:install
The generators (i) append routes, (ii) create initialiser stubs under config/initializers, and (iii) scaffold spec/openapi_helper.rb, which wires the RSwag DSL into RSpec’s configuration.
4 Worked Example
4.1 Domain Model
For concreteness, consider a minimal Post resource (title:string, body:text) generated via Rails scaffolding.
4.2 RSpec + RSwag Specification
spec/requests/posts_spec.rb:
require 'openapi_helper'
RSpec.describe 'Posts API', type: :request do
path '/posts' do # ← OpenAPI “path” object
post 'Creates a post' do
tags 'Posts'
consumes 'application/json'
parameter name: :post, in: :body, schema: {
type: :object,
properties: {
title: { type: :string },
body: { type: :string }
},
required: %w[title body]
}
response '201', 'created' do
let(:post) { { title: 'Hello', body: 'World' } }
run_test! # issues POST /posts and asserts 201
end
response '422', 'invalid' do
let(:post) { { title: '' } }
run_test!
end
end
end
end
Interpretation. The path block maps one-to-one with an OpenAPI path item. Declarative constructs (parameter, response) populate the metadata tree, whereas run_test! executes the HTTP request and fails the example upon behavioural divergence—thereby treating documentation as a compile-time artefact.
4.3 Compilation to OpenAPI
Running the test suite followed by the Rake task:
bundle exec rspec
rake rswag:specs:swaggerize # alias: rake rswag
produces a canonical YAML specification (swagger/v1/swagger.yaml). Build pipelines commonly cache this artefact and fail if its checksum diverges from version control, preventing undocumented changes from reaching production.
4.4 Interactive Exploration
Launching the Rails server exposes the UI at http://localhost:3000/api-docs. The “Try it out” feature sends live requests to the development server, facilitating rapid feedback for front-end and third-party consumers.
🌅 Real-World Example: Swagger in Action
Want to see how Swagger (OpenAPI) is used in a live Ruby on Rails project? This example integrates rswag into a functional API backend—perfect for deepening your understanding beyond documentation.
🔗 View the Repo on GitHub5 Evaluation

Empirical experience on production systems indicates a measurable reduction in support round-trips and onboarding time. Quantitative analysis of defect reports pre- and post-adoption, though outside this paper’s scope, is an intriguing avenue for future work.
6 Discussion
- Versioning. Multiple documents (v1/swagger.yaml, v2/swagger.yaml) may be declared in config/initializers/rswag_api.rb to capture breaking changes.
- Security Schemes. JWT, API keys, or OAuth2 flows are expressible via security_scheme helpers, ensuring that UI consumers are prompted for correct credentials.
- Schema Reuse. RSwag supports $ref pointers to external schema files, encouraging DRY design across large code-bases.
- Production Deployment. In high-throughput environments, teams frequently serve the generated YAML via Rails but offload the heavy Swagger UI assets to a CDN or NGINX, thereby eliminating Ruby middleware from the critical path.
7 Conclusion
RSwag operationalises the maxim “tests are documentation” by materialising OpenAPI specifications as an artefact of the RSpec cycle. The approach delivers verifiable, interactive, and version-controlled API contracts at negligible marginal cost, thereby aligning developer productivity with consumer trust.


References
- Swagger/OpenAPI Specification 3.0.3. OpenAPI Initiative, 2021.
- RSwag GitHub Repository, README.md, accessed 9 June 2025.
- Fowler, M., Continuous Integration. Addison-Wesley, 2006.
Nice option. You can take a look to https://github.com/a-chacon/oas_rails too. Not all Rails projects relies on Rspec for testing. So this project is “framework-agnostic” and just depend on tagging your controllers.