Solid Cable : WebSockets et temps réel sans Redis


Bienvenue dans ce second article de notre série sur le Triumvirat "Solid" dans Rails 8 ! Aujourd’hui, on parle d’un sujet brûlant si vous souhaitez faire un Rails app qui vit dans le présent : le temps réel.


Solid Cable, c’est la nouvelle façon d’intégrer des WebSockets dans Rails sans se prendre la tête avec Redis ou des serveurs externes. C’est natif, c’est simple, et c’est puissant.


Mais pourquoi le temps réel est-il si important aujourd’hui ? Parce que vos utilisateurs s’y attendent. Voici quelques cas concrets où Solid Cable brille :

  1. 💬 Un chat en direct entre utilisateurs, sans recharger la page
  2. 📈 Un dashboard qui se met à jour automatiquement quand les données changent
  3. 🔔 Des notifications instantanées dès qu’un événement survient
  4. 🛒 Un panier partagé qui se synchronise en live entre plusieurs appareils
  5. 🎮 Une app collaborative où plusieurs personnes interagissent en même temps


Avec Solid Cable, tout ça devient possible sans friction. Dans cet article, on va voir comment l’installer, le configurer, et surtout comment l’utiliser pour créer des expériences dynamiques et modernes.


N'hésitez pas à parcourir mes autres articles sur le sujet Triumvirat "Solid" qui n'aura plus de secret pour vous !


  1. "Solid Cache" : Ne plus dépendre de Redis pour le cache dans Rails
  2. "Solid Cable" : Des websockets et du temps réel simplement et sans prise de tête (vous êtes ici)
  3. "Solid Queue" : Des taches de fonds à la sauce Rails
  4. Le triumvirat appliqué à un projet complet


Accrochez ça va être du solide :)

Solid Cable : WebSockets Sans Redis dans Rails 8

Comprendre Action Cable et le temps réel

Action Cable est la solution de Rails pour ajouter des fonctionnalités en temps réel à votre application. Pensez à :

  1. Un chat en direct
  2. Des notifications instantanées
  3. Des tableaux de bord avec données live
  4. Une collaboration en temps réel (comme Google Docs)

Comment fonctionnent les WebSockets ?

Les WebSockets sont comme un téléphone toujours décroché entre le client et le serveur :


HTTP classique :

Client: "Bonjour serveur, quoi de neuf ?"
Serveur: "Rien de spécial. Au revoir."
[Connection fermée]
[10 secondes plus tard]
Client: "Bonjour serveur, quoi de neuf maintenant ?"
Serveur: "Toujours rien. Au revoir."


WebSocket :

Client: "Bonjour serveur, je reste en ligne"
Serveur: "OK, je te préviens s'il y a du nouveau"
[Connection reste ouverte]
Serveur: "Hey ! Nouveau message !"
Client: "Merci, je l'affiche tout de suite"

Le rôle de Solid Cable

Traditionnellement, Action Cable utilisait Redis comme "central téléphonique" pour router les messages entre les différents processus de votre application.

Solid Cable remplace Redis par une table de base de données avec un système de polling (interrogation régulière).

L'architecture de Solid Cable

Solid Cable crée une table simple :

# db/cable_schema.rb
create_table "solid_cable_messages", force: :cascade do |t|
t.binary "channel", null: false # Le canal de communication
t.binary "payload", null: false # Le message lui-même
t.datetime "created_at", null: false
t.bigint "channel_hash", null: false # Hash du canal pour recherche rapide
end


Le fonctionnement :

  1. Un client se connecte via WebSocket
  2. Quand un message doit être envoyé, il est écrit dans cette table
  3. Un système de polling vérifie régulièrement (par défaut toutes les 0.1 secondes) s'il y a de nouveaux messages
  4. Les messages sont transmis aux clients connectés
  5. Les vieux messages sont automatiquement supprimés après 1 jour

Installation et Configuration

Sur Rails 8

Comme pour Solid Cache, Solid Cable est activé par défaut en production sur Rails 8 !

Vérifiez votre config/cable.yml :


production:
adapter: solid_cable
connects_to:
database:
writing: cable
polling_interval: 0.1.seconds
message_retention: 1.day

Configuration pour le développement

Par défaut, Rails 8 utilise l'adaptateur async en développement. Pour utiliser Solid Cable en dev :


# config/cable.yml
development:
adapter: solid_cable
connects_to:
database:
writing: cable
polling_interval: 0.1.seconds
message_retention: 1.day

Puis configurez votre config/database.yml :


development:
primary:
<<: *default
database: mon_app_development
cable:
<<: *default
database: mon_app_cable_development

Exemple Complet : Chat en Temps Réel

Construisons une application de chat simple pour illustrer Solid Cable.

Étape 0 : Créer un nouveau projet

# Vérifiez que vous avez Rails 8
rails -v
> 8.0.X
# Créez un nouveau projet
rails new chat_app
cd chat_app


Configurez cable.yml pour utiliser solid_cable au lieu de async en développement.

# Async adapter only works within the same process, so for manually triggering cable updates from a console,
# and seeing results in the browser, you must do so from the web console (running inside the dev process),
# not a terminal started via bin/rails console! Add "console" to any action or any ERB template view
# to make the web console appear.
development:
adapter: solid_cable
test:
adapter: test
production:
adapter: solid_cable
connects_to:
database:
writing: cable
polling_interval: 0.1.seconds
message_retention: 1.day

En développement il faut ajouter le schéma de la base de donnée solid_cable dans la base de donnée. En production, on aura une base de donnée dédiée donc pas besoin.


bin/rails db:schema:load SCHEMA=db/cable_schema.rb


Étape 1 : Créer le modèle

rails g model Message content:text
rails db:migrate

Étape 2 : Créer le canal

# app/channels/chat_channel.rb
class ChatChannel < ApplicationCable::Channel
def subscribed
# S'abonne au stream "chat"
stream_from "chat"
end
def unsubscribed
# Nettoyage si nécessaire
end
def speak(data)
# Méthode appelée quand un message est envoyé
message = Message.create!(
content: data['message']
)
end
end

Étape 3 : Le modèle avec broadcast

# app/models/message.rb
class Message < ApplicationRecord
# Après création, broadcaster le message à tous les clients connectés
after_create_commit do
broadcast_append_to(
"chat",
target: "messages",
partial: "messages/message",
locals: { message: self }
)
end
end

Étape 4 : Le contrôleur

# app/controllers/messages_controller.rb
class MessagesController < ApplicationController
def index
@messages = Message.order(created_at: :desc).limit(50)
end
def create
@message = Message.new(message_params)
if @message.save
# Le broadcast est géré automatiquement par le callback
head :ok
else
render json: { errors: @message.errors }, status: :unprocessable_entity
end
end
private
def message_params
params.require(:message).permit(:content)
end
end

Étape 5 : La vue

<!-- app/views/messages/index.html.erb -->
<div class="chat-container">
<h1>Chat en Direct</h1>
<%= turbo_stream_from "chat" %>
<!-- Zone d'affichage des messages -->
<div id="messages" class="messages-list">
<%= render @messages %>
</div>
<!-- Formulaire d'envoi -->
<%= form_with(
model: Message.new,
id: "message-form"
) do |form| %>
<%= form.text_field :content,
placeholder: "Tapez votre message..." %>
<%= form.submit "Envoyer" %>
<% end %>
</div>



<!-- app/views/messages/_message.html.erb -->
<div class="message" id="<%= dom_id(message) %>">
<%= message.content %>
<span class="timestamp"><%= time_ago_in_words(message.created_at) %> ago</span>
</div>

Étape 6 : Routes

# config/routes.rb
Rails.application.routes.draw do
resources :messages, only: [:index, :create]
root "messages#index"
end

Tester en Action

  1. Lancez votre serveur : bin/dev
  2. Ouvrez deux fenêtres de navigateur sur http://localhost:3000
  3. Tapez un message dans une fenêtre
  4. Voyez-le apparaître instantanément dans l'autre !


Ce chat en temps réel s’appuie sur Turbo Streams et Solid Cable: la page s’abonne au flux avec turbo_stream_from "chat" . Lorsqu’un message est soumis via form_with , le contrôleur crée un enregistrement Message .

Après le commit, le modèle déclenche broadcast_append_to "chat" , et Solid Cable (adapter ActionCable en production) persiste et distribue ce broadcast.

Côté client, @hotwired/turbo-rails reçoit automatiquement le flux et met à jour le DOM en ajoutant le nouveau message dans #messages , sans JavaScript personnalisé ni rechargement de page.

Monitoring et Debugging

Vérifier les messages dans la base

# Console Rails
SolidCable::Message.count
# Devrait être faible car les messages sont supprimés après 1 jour
SolidCable::Message.last
# Voir le dernier message broadcasté

Voir les logs

# Dans vos logs Rails, vous verrez :
SolidCable::Message Insert (0.5ms)
INSERT INTO "solid_cable_messages" ...
Turbo::StreamsChannel transmitting
"<turbo-stream action='append' target='messages'>..."

Solid Cable vs Autres Solutions

Solution
Vitesse
Setup
Scalabilité
Cas d'usage
Solid Cable
Bonne
Très simple
Moyenne
Apps petites/moyennes
Action Cable (Redis)
Très bonne
Simple
Bonne
Apps moyennes
AnyCable
Excellente
Complexe
Excellente
Apps à grande échelle


Utilisez Solid Cable si :

  1. Vous démarrez une nouvelle app Rails 8
  2. Vous avez besoin de fonctionnalités temps réel basiques
  3. Vous voulez éviter Redis
  4. Vous avez moins de 1000 connexions simultanées

Passez à Action Cable + Redis si :

  1. Vous avez besoin de meilleures performances
  2. Vous avez déjà Redis dans votre stack

Passez à AnyCable si :

  1. Vous avez des milliers de connexions simultanées
  2. La latence est critique


Conclusion : Solid Cable, le temps réel sans compromis

Solid Cable redéfinit la manière dont on pense le temps réel dans Rails. Fini les configurations complexes avec Redis ou des serveurs externes : tout fonctionne en local, avec une intégration fluide et une API familière. Que ce soit pour un chat, des notifications, des dashboards ou des expériences collaboratives, Solid Cable permet de créer des interfaces réactives et modernes sans sacrifier la simplicité.

Avec Rails 8 qui l’adopte officiellement, Solid Cable devient un outil incontournable pour tout développeur qui veut offrir une expérience utilisateur dynamique et instantanée.


Moins de dépendances, plus d’interactions. Solid Cable, c’est Rails en temps réel, comme il se doit.