Undokumentierte Rails-APIs kosten Teams Stunden pro Woche: Slack-Fragen, fehlerhafte Integrationen, mühsames Onboarding. OpenAPI liefert eine maschinenlesbare Spezifikation, aus der sich interaktive Dokumentation, Client-SDKs und Mock-Server generieren lassen.
Dieser Leitfaden behandelt die zwei wichtigsten Rails-Tools für OpenAPI-Dokumentation, ihre Praxis-Trade-offs und das CI-Setup, das Spec-Drift verhindert.
Warum die meisten Rails-API-Docs veralten
Das Problem ist nicht die Generierung der Dokumentation. Das Problem ist, sie nach dem initialen Setup aktuell zu halten. Entwickler fügen Parameter hinzu, ändern Response-Strukturen und vergessen, die Spec neu zu generieren. Nach wenigen Wochen beschreibt die OpenAPI-Datei eine API, die so nicht mehr existiert.
Die Lösung: Dokumentationsgenerierung an die Test-Suite und CI-Pipeline koppeln, sodass veraltete Specs den Build brechen.
Rails 7 #131 API-Dokumentation mit OpenAPI, Swagger, RSWAG. Manifest mit ChatGPT generieren?!
RSwag: Testgetriebene OpenAPI-Specs
RSwag (aktuell v2.16.0, Stand März 2026) integriert sich direkt in RSpec. Jeder Request-Spec dokumentiert gleichzeitig den Endpunkt und verifiziert, dass die API sich wie beschrieben verhält.
Installation (ca. 15 Minuten)
# Gemfile
group :development, :test do
gem 'rswag', '~> 2.16'
gem 'rspec-rails', '~> 7.1'
end
bundle install
rails generate rswag:install
Der Generator erstellt spec/swagger_helper.rb mit globalen Einstellungen (API-Version, Basis-URL, Auth-Schema).
Einen Endpunkt dokumentieren und testen
# spec/requests/api/v1/orders_spec.rb
require 'swagger_helper'
RSpec.describe 'Orders API', type: :request do
path '/api/v1/orders' do
get 'Bestellungen auflisten' do
tags 'Orders'
produces 'application/json'
parameter name: :page, in: :query, type: :integer, required: false
parameter name: :per_page, in: :query, type: :integer, required: false
response '200', 'Bestellungen gefunden' do
schema type: :array, items: {
type: :object,
properties: {
id: { type: :integer },
total_cents: { type: :integer, example: 12550 },
currency: { type: :string, example: 'CHF' },
status: { type: :string, enum: %w[pending confirmed shipped] },
created_at: { type: :string, format: 'date-time' }
},
required: %w[id total_cents currency status created_at]
}
let(:page) { 1 }
let(:per_page) { 25 }
run_test!
end
response '401', 'nicht autorisiert' do
run_test!
end
end
end
end
Die run_test!-Methode ist der entscheidende Punkt: Sie führt den tatsächlichen HTTP-Request aus und validiert die Antwort gegen das definierte Schema. Stimmt die Antwort nicht überein, schlägt der Test fehl.
rake rswag:specs:swaggerize
# Generiert swagger/v1/swagger.yaml
USEO’s Take: RSwag in der Praxis
Wir setzen RSwag seit über 4 Jahren in Kundenprojekten ein. Es funktioniert zuverlässig, hat aber reale Wartungskosten:
- Schema-Duplikation: Dasselbe Response-Schema wird in jedem Spec wiederholt. Bei 50+ Endpunkten wird das unübersichtlich. Lösung: Shared Examples und
$ref-Schemas inswagger_helper.rbdefinieren. - Spec-Dateigrösse: RSwag-Specs werden schnell 200+ Zeilen lang. Anders als normale Request-Specs enthalten sie viel Schema-Boilerplate. Das senkt die Bereitschaft, sie zu pflegen.
- Fehlende Response-Body-Validierung:
run_test!prüft nur den Status-Code und die Schema-Struktur, nicht den konkreten Inhalt. Ein Endpunkt kann “200 OK” mit leerer Liste zurückgeben und der Test besteht trotzdem. - Upgrade-Aufwand: Der Wechsel von RSwag 2.x Swagger-2.0-Output zu OpenAPI 3.0 erforderte in einem Projekt ca. 3 Tage Migrationsarbeit.
Trotzdem: Für Teams, die bereits RSpec nutzen, ist RSwag der pragmatischste Weg zu aktueller API-Dokumentation.
OasRails: Annotation-basierte Alternative
OasRails (v0.14.0+) generiert OpenAPI-3.1-Spezifikationen direkt aus YARD-Kommentaren in Controllern. Kein separater Generierungsschritt nötig.
Installation (ca. 10 Minuten)
# Gemfile
gem 'oas_rails', '~> 0.14'
bundle install
# config/routes.rb
Rails.application.routes.draw do
mount OasRails::Engine => '/docs' if Rails.env.development?
end
Endpunkt annotieren
class Api::V1::OrdersController < ApplicationController
# @summary Bestellungen auflisten
# @description Paginierte Liste aller Bestellungen
# @parameter page [Integer] Seitennummer (query)
# @parameter per_page [Integer] Einträge pro Seite (query)
# @response 200 [Array<Order>] Bestellliste
# @response 401 Nicht autorisiert
def index
@orders = Order.page(params[:page]).per(params[:per_page])
render json: @orders
end
end
Dokumentation sofort verfügbar unter http://localhost:3000/docs.
USEO’s Take: OasRails-Erfahrung
OasRails ist attraktiv, weil die Dokumentation direkt beim Code lebt. Aber in der Praxis sehen wir folgende Probleme:
- Kommentare veralten still: Im Gegensatz zu RSwag gibt es keinen automatischen Test, der fehlschlägt, wenn die Kommentare nicht zum Code passen. Ein Entwickler ändert die Response-Struktur, vergisst den YARD-Kommentar, und niemand merkt es.
- Keine Testabdeckung: Die Dokumentation wird generiert, aber nie validiert. Man hat eine schön aussehende Spec, die möglicherweise falsch ist.
- Junges Projekt: OasRails hat weniger Community-Support als RSwag. Bei Problemen findet man weniger Lösungen auf Stack Overflow oder GitHub Issues.
- Gut für interne APIs: Wenn die Dokumentation primär für das eigene Team ist und nicht für externe Konsumenten, kann der geringere Overhead sinnvoll sein.
RSwag vs OasRails: Direktvergleich
| Kriterium | RSwag | OasRails |
|---|---|---|
| OpenAPI-Version | 3.0 (OAS 3.1 experimentell) | 3.1 nativ |
| Dokumentationsquelle | RSpec Request-Specs | YARD-Kommentare |
| Validierung | Automatisch via Tests | Keine (nur Generierung) |
| Setup-Zeit | ~15 Min | ~10 Min |
| Wartungsaufwand | Mittel (Schema-Boilerplate) | Niedrig (aber ohne Sicherheitsnetz) |
| CI-Integration | Natürlich (Teil der Test-Suite) | Erfordert separaten Check |
| Empfohlen für | Externe APIs, regulierte Umgebungen | Interne APIs, Prototypen |
CI-Pipeline: Spec-Drift verhindern
Der grösste Fehler, den wir bei Kunden sehen: RSwag wird installiert, die initiale Spec generiert, und dann nie wieder aktualisiert. Nach 3 Monaten ist die Dokumentation Fiktion.
GitHub Actions Workflow
name: API Docs
on: [push, pull_request]
jobs:
verify-api-docs:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_PASSWORD: postgres
ports: ['5432:5432']
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Setup DB
run: bundle exec rails db:test:prepare
- name: Generate OpenAPI spec
run: bundle exec rake rswag:specs:swaggerize
- name: Fail if spec changed
run: |
git diff --exit-code swagger/
echo "OpenAPI spec is up to date"
Der entscheidende Schritt ist git diff --exit-code swagger/. Wenn ein Entwickler einen Endpunkt ändert, den RSwag-Spec aktualisiert, aber vergisst, die YAML-Datei neu zu generieren und einzuchecken, schlägt der Build fehl.
Alternative: Spec in CI generieren und als Artefakt speichern
Für Teams, die die generierte Spec nicht im Repository haben wollen:
- name: Upload spec
uses: actions/upload-artifact@v4
with:
name: openapi-spec
path: swagger/v1/swagger.yaml
Code-First vs. Design-First: Wann welcher Ansatz?
Die meisten Rails-Teams fahren mit Code-First besser. Der Grund: Rails-Projekte entwickeln sich iterativ. Endpunkte entstehen, ändern sich, werden deprecated. Eine vorab geschriebene Spezifikation ist nach dem zweiten Sprint oft veraltet.
Design-First lohnt sich bei:
- Öffentlichen APIs mit externen Konsumenten
- Stark regulierten Umgebungen (z.B. Finanzbranche in der Schweiz)
- Projekten, in denen Frontend- und Backend-Teams parallel entwickeln
Code-First ist pragmatischer bei:
- Internen APIs
- MVPs und Prototypen
- Teams, die bereits umfangreiche RSpec-Suites haben
In der Praxis kombinieren viele Teams beide Ansätze: Design-First für die initiale API-Planung, dann Code-First (RSwag) für die laufende Wartung.
Interaktive Dokumentation bereitstellen
Wenn die OpenAPI-Spec generiert ist, brauchen Konsumenten eine lesbare Oberfläche.
Swagger UI (klassisch):
# Gemfile
gem 'rswag-ui'
Wird von RSwag automatisch unter /api-docs gemountet.
RapiDoc (modern, bessere Mobile-Ansicht):
OasRails liefert RapiDoc standardmässig unter /docs aus.
Redoc (beste Lesbarkeit für externe Dokumentation): Kann als statische HTML-Seite generiert werden:
npx @redocly/cli build-docs swagger/v1/swagger.yaml -o public/api-docs.html
SDK-Generierung und Mock-Server
Aus einer validen OpenAPI-Spec lassen sich Client-SDKs automatisch generieren:
# TypeScript-Client generieren
npx @openapitools/openapi-generator-cli generate \
-i swagger/v1/swagger.yaml \
-g typescript-fetch \
-o generated/ts-client
Mock-Server für parallele Frontend-Entwicklung:
npx @stoplight/prism-cli mock swagger/v1/swagger.yaml
# Mock-API verfügbar auf http://127.0.0.1:4010
Das Frontend-Team kann sofort gegen realistische API-Antworten entwickeln, bevor das Backend fertig ist.
Zusammenfassung
| Schritt | Tool | Zeitaufwand |
|---|---|---|
| OpenAPI-Spec generieren | RSwag oder OasRails | 15-30 Min Setup |
| CI-Enforcement einrichten | GitHub Actions | 10 Min |
| Interaktive Docs bereitstellen | Swagger UI / RapiDoc | 5 Min |
| SDK generieren | OpenAPI Generator | 5 Min |
| Mock-Server aufsetzen | Prism | 5 Min |
Die wichtigste Erkenntnis: Das Generieren der initialen Spec ist trivial. Die eigentliche Arbeit ist, sie über Monate und Jahre aktuell zu halten. Ohne CI-Enforcement wird jede API-Dokumentation irgendwann zur Lüge.
RSwag mit CI-Integration ist der zuverlässigste Ansatz für Rails-Teams, die ihre API-Dokumentation ernst nehmen.
FAQs
Was ist der Unterschied zwischen Code-First und Design-First?
Code-First bedeutet: API implementieren, Tests schreiben, Dokumentation aus dem Code generieren. Der Vorteil ist, dass die Docs immer das tatsächliche Verhalten widerspiegeln. Der Nachteil: Kein vorab definierter API-Vertrag.
Design-First bedeutet: Zuerst die OpenAPI-Spec schreiben, dann implementieren. Gut für externe APIs und parallele Entwicklung, aber die Spec muss manuell synchron gehalten werden.
Wie verhindere ich, dass die Dokumentation veraltet?
Drei Massnahmen:
- RSwag-Tests in CI: Jeder Build generiert die Spec neu und prüft auf Diff
- PR-Reviews: OpenAPI-Änderungen als Teil des Code-Reviews behandeln
- Swagger UI im Staging: Team und Stakeholder sehen immer den aktuellen Stand
Brauche ich RSwag, wenn ich bereits Request-Specs habe?
Ja, weil Standard-Request-Specs keine OpenAPI-Spec generieren. RSwag erweitert die RSpec-DSL um Schema-Definitionen, die dann in eine valide OpenAPI-YAML-Datei umgewandelt werden. Der Migrationsaufwand bestehender Specs liegt bei ca. 30-60 Minuten pro Controller.