Action Cable et WebSockets dans Rails : Guide Complet pour les Entretiens Techniques
Action Cable integre les WebSockets directement dans Rails. Ce guide approfondi couvre l'architecture des connexions, les channels, Solid Cable, Turbo Streams, le scaling avec Redis et les patterns de test pour les entretiens techniques.

Action Cable représente l'intégration native des WebSockets dans Ruby on Rails, permettant d'établir des connexions bidirectionnelles persistantes entre le serveur et les clients. Cette technologie constitue un pilier fondamental pour le développement d'applications temps réel modernes. Les recruteurs évaluent fréquemment la compréhension des candidats sur ce sujet, car la maîtrise d'Action Cable témoigne d'une expertise approfondie de l'écosystème Rails et des architectures événementielles.
Les questions d'entretien sur Action Cable visent généralement trois axes : l'architecture des connexions et channels, les stratégies de diffusion (broadcasting), et la configuration en production. Une préparation solide sur ces trois piliers permet de démontrer une compréhension complète du framework.
Architecture et Authentification des Connexions
Le point d'entrée d'Action Cable réside dans la classe Connection, responsable de l'authentification et de l'identification de chaque connexion WebSocket. Contrairement aux requêtes HTTP classiques, une connexion WebSocket persiste dans le temps, rendant l'authentification initiale cruciale pour la sécurité de l'application.
# app/channels/application_cable/connection.rb
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
self.current_user = find_verified_user
end
private
def find_verified_user
if verified_user = User.find_by(id: cookies.encrypted[:user_id])
verified_user
else
reject_unauthorized_connection
end
end
end
endLa directive identified_by établit un identifiant unique pour chaque connexion, permettant de cibler des utilisateurs spécifiques lors des diffusions. La méthode find_verified_user illustre l'approche recommandée : utiliser des cookies chiffrés plutôt que des paramètres d'URL, évitant ainsi l'exposition des tokens d'authentification dans les logs serveur.
L'appel à reject_unauthorized_connection ferme immédiatement la connexion WebSocket et déclenche une erreur côté client. Cette approche défensive garantit qu'aucune connexion non authentifiée ne puisse s'établir, même partiellement.
Conception des Channels et Gestion des Abonnements
Les channels constituent l'abstraction principale pour organiser la logique temps réel. Chaque channel encapsule un domaine fonctionnel spécifique et gère le cycle de vie des abonnements ainsi que la réception des messages.
# app/channels/chat_channel.rb
class ChatChannel < ApplicationCable::Channel
def subscribed
room = ChatRoom.find(params[:room_id])
if room.members.include?(current_user)
stream_for room
else
reject
end
end
def receive(data)
message = ChatMessage.create!(
room_id: params[:room_id],
user: current_user,
body: data["body"]
)
ChatChannel.broadcast_to(
message.room,
{ id: message.id, body: message.body, user: current_user.name }
)
end
def unsubscribed
AppearanceTracker.mark_offline(current_user)
end
endLa méthode subscribed effectue une vérification d'autorisation avant d'établir le stream. L'utilisation de stream_for avec un objet Active Record génère automatiquement un nom de stream unique basé sur le modèle, simplifiant la gestion des identifiants.
La méthode receive traite les messages entrants des clients. Elle persiste le message en base de données puis le diffuse à tous les abonnés du salon. Cette séparation entre persistance et diffusion permet de garantir la cohérence des données même en cas de déconnexion temporaire.
Le callback unsubscribed gère le nettoyage lors de la fermeture de connexion, permettant par exemple de mettre à jour le statut de présence des utilisateurs.
Intégration JavaScript Côté Client
L'établissement de la connexion WebSocket côté client s'effectue via le consumer JavaScript fourni par Rails. La configuration des callbacks permet de réagir aux différents événements du cycle de vie de la connexion.
import consumer from "./consumer"
const chatChannel = consumer.subscriptions.create(
{ channel: "ChatChannel", room_id: roomId },
{
connected() {
console.log("Connected to chat room", roomId)
},
disconnected() {
console.log("Disconnected from chat room")
},
received(data) {
const messageList = document.getElementById("messages")
messageList.insertAdjacentHTML("beforeend",
`<div class="message"><strong>${data.user}</strong>: ${data.body}</div>`
)
},
sendMessage(body) {
this.perform("receive", { body: body })
}
}
)Le premier argument de subscriptions.create spécifie le channel et les paramètres transmis à la méthode subscribed côté serveur. Les callbacks connected et disconnected permettent d'adapter l'interface utilisateur selon l'état de la connexion.
La méthode received traite les messages diffusés par le serveur, tandis que sendMessage illustre l'envoi de données vers le serveur via this.perform. Cette méthode invoque la méthode correspondante dans le channel Ruby.
Solid Cable : L'Adaptateur Natif de Rails 8
Rails 8 introduit Solid Cable comme adaptateur par défaut, éliminant la dépendance à Redis pour de nombreux cas d'usage. Solid Cable utilise la base de données existante pour la messagerie, simplifiant considérablement l'infrastructure de déploiement.
# config/cable.yml (Rails 8 default)
development:
adapter: solid_cable
production:
adapter: solid_cable
connects_to:
database:
writing: cable
polling_interval: 0.1.seconds
message_retention: 1.dayLa configuration multi-base de données permet d'isoler les opérations Action Cable sur une base dédiée, évitant toute contention avec les requêtes applicatives principales.
# config/database.yml (Rails 8 multi-database)
production:
primary:
<<: *default
database: myapp_production
cable:
<<: *default
database: myapp_cable_production
migrations_paths: db/cable_migrateCette séparation offre plusieurs avantages : les opérations de polling fréquentes n'impactent pas les performances de la base principale, et la rétention des messages peut être configurée indépendamment. Le paramètre message_retention permet de purger automatiquement les anciens messages, maintenant une empreinte mémoire maîtrisée.
Stratégies de Diffusion et Patterns Courants
La diffusion de messages peut s'effectuer depuis différents contextes applicatifs. Les callbacks de modèle permettent de déclencher des notifications automatiques lors des modifications de données.
# Broadcasting from a model callback
class Notification < ApplicationRecord
belongs_to :user
after_create_commit :broadcast_to_user
private
def broadcast_to_user
ActionCable.server.broadcast(
"notifications_#{user_id}",
{ id: id, title: title, read: false }
)
end
end
# Broadcasting from a background job
class DashboardUpdateJob < ApplicationJob
queue_as :default
def perform(dashboard_id)
dashboard = Dashboard.find(dashboard_id)
stats = dashboard.compute_stats
ActionCable.server.broadcast(
"dashboard_#{dashboard_id}",
{ stats: stats, updated_at: Time.current.iso8601 }
)
end
endL'utilisation de after_create_commit garantit que la diffusion n'intervient qu'après la validation de la transaction, évitant de notifier les clients pour des données qui pourraient être annulées par un rollback.
Les jobs en arrière-plan conviennent particulièrement aux calculs coûteux dont les résultats doivent être diffusés. Cette approche découple le calcul de la diffusion et permet un meilleur contrôle de la charge serveur.
Intégration avec Turbo Streams
Hotwire Turbo simplifie drastiquement l'implémentation du temps réel en automatisant la diffusion et le rendu des mises à jour.
# app/models/message.rb
class Message < ApplicationRecord
belongs_to :chat_room
broadcasts_to :chat_room
end
# app/views/chat_rooms/show.html.erb
<%= turbo_stream_from @chat_room %>
<div id="messages">
<%= render @chat_room.messages %>
</div>La directive broadcasts_to configure automatiquement les callbacks de diffusion pour les opérations CRUD. Côté vue, turbo_stream_from établit l'abonnement WebSocket et applique automatiquement les mises à jour DOM reçues.
Cette intégration réduit considérablement le code boilerplate nécessaire pour les fonctionnalités temps réel standard, tout en restant extensible pour les cas d'usage personnalisés.
Configuration Redis pour la Haute Disponibilité
Pour les déploiements à grande échelle ou multi-serveurs, Redis demeure la solution de référence en raison de ses performances et de sa capacité à gérer des clusters de serveurs applicatifs.
# config/cable.yml — Redis adapter for high-scale production
production:
adapter: redis
url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
channel_prefix: myapp_productionLe paramètre channel_prefix isole les messages de l'application, permettant de partager une instance Redis entre plusieurs applications ou environnements. Cette configuration s'avère indispensable lors de l'utilisation de services Redis managés partagés.
Redis offre également des fonctionnalités avancées comme le pub/sub natif et la persistance optionnelle, garantissant une fiabilité accrue pour les applications critiques.
Tests des Channels Action Cable
Rails fournit une suite complète d'outils de test pour valider le comportement des channels, incluant les helpers pour simuler les connexions et vérifier les diffusions.
# test/channels/chat_channel_test.rb
require "test_helper"
class ChatChannelTest < ActionCable::Channel::TestCase
test "subscribes to a valid room" do
room = chat_rooms(:general)
user = users(:alice)
stub_connection current_user: user
subscribe room_id: room.id
assert subscription.confirmed?
assert_has_stream_for room
end
test "rejects subscription for unauthorized user" do
room = chat_rooms(:private)
user = users(:outsider)
stub_connection current_user: user
subscribe room_id: room.id
assert subscription.rejected?
end
test "broadcasts messages to room subscribers" do
room = chat_rooms(:general)
stub_connection current_user: users(:alice)
subscribe room_id: room.id
assert_broadcast_on(room, hash_including(body: "Hello")) do
perform :receive, body: "Hello"
end
end
endLa méthode stub_connection permet de simuler une connexion authentifiée sans établir de véritable WebSocket. Les assertions assert_has_stream_for et assert_broadcast_on vérifient respectivement l'établissement des streams et le contenu des messages diffusés.
Ces tests unitaires complètent les tests d'intégration système, offrant une couverture rapide et ciblée des règles métier implémentées dans les channels.
Passez à la pratique !
Conclusion
Action Cable représente une solution mature et intégrée pour les fonctionnalités temps réel dans Rails. La compréhension approfondie de son architecture, depuis l'authentification des connexions jusqu'aux stratégies de diffusion, constitue un atout majeur lors des entretiens techniques. Les évolutions récentes comme Solid Cable et l'intégration Turbo Streams témoignent de l'engagement continu de l'équipe Rails à simplifier le développement d'applications réactives.
La maîtrise des patterns de test spécifiques à Action Cable démontre également une approche professionnelle du développement, garantissant la fiabilité des fonctionnalités temps réel en production.
Pratiquer les questions d'entretien ActionCable et WebSockets
Passe à la pratique !
Teste tes connaissances avec nos simulateurs d'entretien et tests techniques.
Tags
Partager
Articles similaires

ActiveRecord : Optimiser les requêtes N+1 dans Ruby on Rails
Guide complet pour détecter et corriger les problèmes de requêtes N+1 dans Rails avec ActiveRecord. Includes, preload, eager_load et outils de détection.

Questions d'entretien Ruby on Rails : Top 25 en 2026
Les 25 questions d'entretien Ruby on Rails les plus posées. Architecture MVC, Active Record, migrations, tests RSpec, API REST avec réponses détaillées et exemples de code.

Ruby on Rails 7 : Hotwire et Turbo pour des applications réactives
Guide complet sur Hotwire et Turbo dans Rails 7. Apprenez à créer des applications réactives sans écrire de JavaScript avec Turbo Drive, Frames et Streams.