Introduzione
Se hai mai desiderato che la tua app Rails sembrasse viva, dovresti dare un'occhiata a Action Cable. È il modo integrato di Rails per gestire i WebSockets, il che significa che il tuo server e il browser possono rimanere connessi e comunicare in tempo reale. Niente più aggiornamenti di pagina, niente polling ingombrante: gli aggiornamenti appaiono istantaneamente.
In questa guida, costruiremo una divertente demo: un contatore di traffico live. Quando qualcuno visita il tuo sito, registreremo quella visita nel database, incrementeremo alcuni contatori in memoria e trasmetteremo i numeri aggiornati a tutti online. Chiudi la scheda? Il conteggio degli utenti online scende immediatamente. È semplice, ma mostra la magia in tempo reale che Action Cable porta a Rails 7.
Passo 1: Il Modello di Visita
Per prima cosa, creiamo un modello per registrare le visite.
bin/rails g model Visit session_id:string ip:string user_agent:string
bin/rails db:migrate
# app/models/visit.rb
class Visit < ApplicationRecord
end
Passo 2: Creare una Connessione Personalizzata
Rails ti fornisce già due classi base in app/channels/application_cable/:
- channel.rb → la classe base per tutti i tuoi canali.
- connection.rb → la classe base per tutte le tue connessioni WebSocket.
Di solito non le modifichiamo. Invece, le estendiamo creando la nostra classe di connessione all'interno di app/channels/. Questo mantiene i valori predefiniti puliti e mette la nostra logica in un posto chiaro.
# app/channels/traffic_connection.rb
module ApplicationCable
class TrafficConnection < Connection
identified_by :session_id, :ip, :user_agent
def connect
self.session_id = request.session.id
self.ip = request.ip
self.user_agent = request.user_agent
end
end
end
Passo 3: Contatori in Memoria
Utilizzeremo contatori atomici per rendere le cose veloci. All'avvio, prendiamo il totale delle visite dal DB e iniziamo gli utenti online da zero.
# config/initializers/traffic_counter.rb
$online_users = Concurrent::AtomicFixnum.new(0)
$total_visits = Concurrent::AtomicFixnum.new(Visit.count)
Passo 4: Il Canale
Qui è dove avviene il divertimento: registriamo la visita, aggiorniamo i contatori e trasmettiamo.
# app/channels/traffic_channel.rb
class TrafficChannel < ApplicationCable::Channel
def subscribed
# registra la visita
Visit.create!(session_id: connection.session_id,
ip: connection.ip,
user_agent: connection.user_agent)
# aggiorna i contatori
$online_users.increment
$total_visits.increment
stream_from "traffic_channel"
broadcast_counts
end
def unsubscribed
$online_users.decrement
broadcast_counts
end
private
def broadcast_counts
ActionCable.server.broadcast("traffic_channel", {
online: $online_users.value,
total: $total_visits.value
})
end
end
Passo 5: Il Lato JavaScript
Quando esegui bin/rails generate channel Traffic, Rails crea due file: il canale Ruby e il file di sottoscrizione JavaScript. Per impostazione predefinita, il file JS importa consumer.js, che Rails ha anche impostato per te quando è stata generata l'app.
// app/javascript/channels/traffic_channel.js
import consumer from "./consumer"
consumer.subscriptions.create("TrafficChannel", {
received(data) {
document.querySelector("#online-count").textContent = data.online
document.querySelector("#total-count").textContent = data.total
}
})
Il file consumer.js viene generato da Rails quando crei una nuova app. Imposta la connessione WebSocket globale a /cable e appare così:
// app/javascript/channels/consumer.js
import { createConsumer } from "@rails/actioncable"
export default createConsumer()
Passo 6: La Vista
<h1>🚦 Traffico Live</h1>
<p>Attualmente online: <span id="online-count">0</span></p>
<p>Visite totali: <span id="total-count"><%= Visit.count %></span></p>
Passo 7: Rotte
# config/routes.rb
Rails.application.routes.draw do
root "home#index"
mount ActionCable.server => "/cable"
end
Passo 8: Provalo
Esegui la tua app con bin/dev. Apri il tuo sito in alcune schede. Il conteggio degli utenti online aumenta con ognuna di esse e scende quando le chiudi. Le visite totali continuano a salire. È super soddisfacente da vedere!
Note per la Produzione
- Hai più worker Puma? Usa Redis per i contatori: la memoria non si sincronizza tra i processi.
- Vuoi tracciare utenti reali invece delle sessioni? Aggiungi current_user nella connessione.
- Memorizzare le visite nel DB significa che puoi eseguire analisi in seguito, come traffico giornaliero o suddivisioni per browser.
E questo è tutto: un contatore di traffico live in tempo reale in Rails 7 con Action Cable. In meno di 100 righe di codice, hai aggiornamenti istantanei e un assaggio di cosa possono fare i WebSockets. Questa stessa configurazione funziona per notifiche, dashboard e tutti i tipi di funzionalità in tempo reale. Una volta che l'hai provato, vorrai spargerlo ovunque.