# Ruby on Rails 7: Hotwire und Turbo fuer reaktive Anwendungen
> Vollstaendiger Leitfaden zu Hotwire und Turbo in Rails 7. Reaktive Anwendungen ohne JavaScript mit Turbo Drive, Frames und Streams entwickeln.
- Published: 2026-01-11
- Updated: 2026-04-07
- Author: SharpSkill
- Tags: ruby on rails, hotwire, turbo, turbo frames, turbo streams
- Reading time: 12 min
---
Rails 7 hat die Webentwicklung revolutioniert, indem Hotwire standardmaessig integriert wurde. Dieser Stack ermoeglicht es, hochreaktive Anwendungen zu erstellen, ohne eine einzige Zeile benutzerdefinierten JavaScript-Code zu schreiben. Turbo Drive, Turbo Frames und Turbo Streams ersetzen traditionelle SPA-Ansaetze durch eine "HTML ueber den Draht"-Philosophie.
> **Warum Hotwire?**
>
> Hotwire reduziert die Frontend-Komplexitaet drastisch. Kein React oder Vue fuer dynamische Oberflaechen noetig: Der Server sendet gebrauchsfertiges HTML, und Turbo uebernimmt die DOM-Aktualisierungen automatisch.
## Die Hotwire-Architektur verstehen
Hotwire besteht aus drei komplementaeren Technologien, die zusammenarbeiten, um eine fluessige Benutzererfahrung ohne die typische JavaScript-Framework-Komplexitaet zu bieten.
**Turbo Drive** beschleunigt die Navigation, indem Link-Klicks und Formularuebermittlungen abgefangen werden. Statt die gesamte Seite neu zu laden, wird nur der Inhalt des `
` ersetzt, wobei der JavaScript- und CSS-Kontext erhalten bleibt.
**Turbo Frames** zerlegen Seiten in unabhaengige Abschnitte. Jeder Frame kann separat aktualisiert werden, was gezielte Interaktionen ermoeglicht, ohne den Rest der Seite zu beeinflussen.
**Turbo Streams** ermoeglichen Echtzeit-Aktualisierungen ueber WebSocket oder als Antwort auf HTTP-Anfragen. Acht CRUD-Aktionen stehen fuer deklarative DOM-Manipulation zur Verfuegung.
```ruby
# Gemfile
# Installing Turbo Rails (included by default in Rails 7+)
gem 'turbo-rails'
```
Fuer bestehende Projekte erfordert die Installation nur einen Befehl.
```bash
# installation.sh
# Installing Turbo in an existing Rails project
rails turbo:install
# Verify the JavaScript import is present
cat app/javascript/application.js
# Should contain: import "@hotwired/turbo-rails"
```
## Initiale Turbo Drive Konfiguration
Turbo Drive ist in Rails 7 standardmaessig aktiviert. Alle Navigation wird automatisch zu "Turbo", ohne zusaetzliche Konfiguration. Das Verhalten kann ueber Data-Attribute angepasst werden.
```erb
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_importmap_tags %>
<%= yield %>
```
Turbo Drive kann bei Bedarf fuer bestimmte Links oder Formulare deaktiviert werden.
```erb
<%= link_to "Dashboard", dashboard_path %>
<%= link_to "Download PDF", export_path, data: { turbo: false } %>
<%= form_with model: @document, data: { turbo: false } do |f| %>
<%= f.file_field :attachment %>
<%= f.submit "Upload" %>
<% end %>
<%= link_to "Delete", item_path(@item),
data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>
```
> **Turbo Drive Cache**
>
> Turbo Drive speichert besuchte Seiten im Cache. Das Attribut `data-turbo-track="reload"` bei Assets erzwingt ein vollstaendiges Neuladen, wenn sich CSS/JS-Dateien aendern.
## Turbo Frames fuer gezielte Aktualisierungen
Turbo Frames definieren Seitenbereiche, die unabhaengig aktualisiert werden. Jeder Frame hat einen eindeutigen Bezeichner und reagiert nur auf Antworten, die einen passenden Frame enthalten.
```erb
Messages
<%= render @messages %>
<%= link_to "Load more", messages_path(page: @next_page) %>
<%= render "form", message: Message.new %>
```
Die Serverantwort muss einen Frame mit demselben Bezeichner enthalten, damit die Aktualisierung funktioniert.
```erb
```
### Lazy Loading mit Turbo Frames
Frames koennen ihren Inhalt asynchron ueber das `src`-Attribut laden. Der initiale Inhalt wird waehrend des Ladens angezeigt.
```erb
Dashboard
Loading statistics...
Loading notifications...
<%= render "activity/placeholder" %>
```
Der Controller antwortet mit einer View, die nur den angeforderten Frame enthaelt.
```ruby
# app/controllers/dashboard_controller.rb
class DashboardController < ApplicationController
def stats
@user_count = User.count
@message_count = Message.count
@active_today = User.where("last_seen_at > ?", 24.hours.ago).count
# Partial rendering for the frame
render partial: "dashboard/stats"
end
end
```
```erb
<%= @user_count %>
Users
<%= @message_count %>
Messages
<%= @active_today %>
Active today
```
## Turbo Streams fuer Echtzeit-Aktualisierungen
Turbo Streams bieten acht Aktionen zur DOM-Manipulation: `append`, `prepend`, `replace`, `update`, `remove`, `before`, `after` und `morph`. Diese Aktionen koennen ueber HTTP-Antwort oder WebSocket ausgeloest werden.
```ruby
# app/controllers/messages_controller.rb
class MessagesController < ApplicationController
def create
@message = current_user.messages.build(message_params)
respond_to do |format|
if @message.save
# Turbo Stream response to add the message
format.turbo_stream do
render turbo_stream: [
turbo_stream.prepend("messages", @message),
turbo_stream.update("message_count", partial: "messages/count"),
turbo_stream.replace("new_message", partial: "messages/form",
locals: { message: Message.new })
]
end
format.html { redirect_to messages_path, notice: "Message created" }
else
format.turbo_stream do
render turbo_stream: turbo_stream.replace(
"new_message",
partial: "messages/form",
locals: { message: @message }
)
end
format.html { render :new, status: :unprocessable_entity }
end
end
end
def destroy
@message = Message.find(params[:id])
@message.destroy
respond_to do |format|
# Removal with animation
format.turbo_stream { render turbo_stream: turbo_stream.remove(@message) }
format.html { redirect_to messages_path, notice: "Message deleted" }
end
end
end
```
### Dedizierte Turbo Stream Templates
Fuer komplexere Antworten bietet ein `.turbo_stream.erb`-Template mehr Flexibilitaet.
```erb
<%= turbo_stream.prepend "messages" do %>
<%= render @message %>
<% end %>
<%= turbo_stream.update "message_count" do %>
<%= Message.count %> messages
<% end %>
<%= turbo_stream.replace "new_message" do %>
<%= render "form", message: Message.new %>
<% end %>
<%= turbo_stream.prepend "flash_messages" do %>
Message sent successfully!
<% end %>
```
> **Antwortformat**
>
> Turbo Stream-Antworten muessen den Content-Type `text/vnd.turbo-stream.html` haben. Rails handhabt dies automatisch mit `respond_to` und dem `turbo_stream`-Format.
## Echtzeit-Broadcasting mit Action Cable
Turbo Streams entfalten ihre volle Staerke beim WebSocket-Broadcasting. Benutzer erhalten Aktualisierungen sofort ohne Polling.
```ruby
# app/models/message.rb
class Message < ApplicationRecord
belongs_to :room
belongs_to :author, class_name: "User"
# Automatic broadcast after creation
after_create_commit do
broadcast_append_to(
room,
target: "messages",
partial: "messages/message",
locals: { message: self }
)
end
# Broadcast after update
after_update_commit do
broadcast_replace_to(
room,
target: dom_id(self),
partial: "messages/message",
locals: { message: self }
)
end
# Broadcast after deletion
after_destroy_commit do
broadcast_remove_to(room, target: dom_id(self))
end
end
```
Die View abonniert den entsprechenden Stream mit dem `turbo_stream_from`-Helper.
```erb
<% end %>
```
### Navigation ausserhalb des uebergeordneten Frames
Standardmaessig bleiben Links in einem Frame innerhalb dieses Frames. Das Attribut `data-turbo-frame` ermoeglicht es, einen anderen Frame oder die gesamte Seite anzusprechen.
```erb
```
```erb
<%= yield %>
```
> **Turbo Debugging**
>
> In der Entwicklungsumgebung die JavaScript-Konsole oeffnen und `Turbo.setProgressBarDelay(0)` eingeben, um die Fortschrittsleiste sofort zu sehen. `Turbo.session.drive = false` deaktiviert Turbo Drive voruebergehend.
## Fehlerbehandlung und Ladezustaende
Eine gute UX erfordert die Behandlung von Ladezustaenden und Netzwerkfehlern.
```erb
<%= form_with model: @model,
data: {
controller: "form-loading",
action: "turbo:submit-start->form-loading#disable turbo:submit-end->form-loading#enable"
} do |f| %>
<%= yield f %>
<% end %>
```
```javascript
// app/javascript/controllers/form_loading_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = ["submit", "text", "spinner"]
disable() {
this.submitTarget.disabled = true
this.textTarget.classList.add("hidden")
this.spinnerTarget.classList.remove("hidden")
}
enable() {
this.submitTarget.disabled = false
this.textTarget.classList.remove("hidden")
this.spinnerTarget.classList.add("hidden")
}
}
```
### Serverfehlerbehandlung
```ruby
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
rescue_from ActiveRecord::RecordNotFound do |exception|
respond_to do |format|
format.turbo_stream do
render turbo_stream: turbo_stream.replace(
"main_content",
partial: "shared/not_found"
)
end
format.html { render "errors/not_found", status: :not_found }
end
end
end
```
## Performance-Optimierung
Mehrere Techniken stellen performante Turbo-Anwendungen sicher.
```ruby
# app/controllers/messages_controller.rb
class MessagesController < ApplicationController
# Avoid N+1 queries with eager loading
def index
@messages = Message.includes(:author, :room)
.order(created_at: :desc)
.page(params[:page])
end
# Fragment caching for static elements
def show
@message = Message.find(params[:id])
fresh_when @message
end
end
```
```erb
<% cache message do %>
<%= message.content %>
By <%= message.author.name %>
<% end %>
```
## Fazit
Hotwire und Turbo transformieren die Rails-Entwicklung, indem sie die Komplexitaet traditioneller JavaScript-Frameworks eliminieren. Turbo Drive beschleunigt die Navigation, Turbo Frames ermoeglichen gezielte Aktualisierungen, und Turbo Streams bieten leistungsstarke Echtzeit-Faehigkeiten.
### Checkliste fuer den Einstieg mit Hotwire
- Rails 7+ fuer integrierte Hotwire-Unterstuetzung verwenden
- Die drei Komponenten verstehen: Drive, Frames und Streams
- Seitenbereiche identifizieren, die von Turbo Frames profitieren
- `respond_to` mit `format.turbo_stream` in Controllern verwenden
- Broadcasting fuer Echtzeit-Features implementieren
- Mit Stimulus fuer einfache JavaScript-Interaktionen kombinieren
Dieser "HTML ueber den Draht"-Ansatz ermoeglicht es, moderne, reaktive Anwendungen zu erstellen und gleichzeitig die Einfachheit und Produktivitaet beizubehalten, die Ruby on Rails so leistungsstark machen. Das Ergebnis: weniger Code zu warten, hervorragende Performance und eine optimale Entwicklererfahrung.
---
Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack.
HTML version of this page: https://sharpskill.dev/de/blog/ruby-on-rails/ruby-on-rails-7-hotwire-turbo