Introdução
Se você já quis que seu aplicativo Rails parecesse vivo, você deve conferir Action Cable. É a maneira integrada do Rails de fazer WebSockets, o que basicamente significa que seu servidor e o navegador podem permanecer conectados e conversar em tempo real. Chega de atualizações de página, sem polling desajeitado — as atualizações aparecem instantaneamente.
Neste guia, vamos construir uma demonstração divertida: um contador de tráfego ao vivo. Quando alguém acessa seu site, vamos registrar essa visita no banco de dados, aumentar alguns contadores na memória e transmitir os números atualizados para todos online. Fechou a aba? A contagem de usuários online cai imediatamente. É simples, mas mostra a mágica em tempo real que o Action Cable traz para o Rails 7.
Passo 1: O Modelo de Visita
Primeiro, vamos criar um modelo para registrar visitas.
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: Criando uma Conexão Personalizada
O Rails já te dá duas classes base em app/channels/application_cable/:
- channel.rb → a classe base para todos os seus canais.
- connection.rb → a classe base para todas as suas conexões WebSocket.
Normalmente, não editamos essas classes. Em vez disso, as estendemos criando nossa própria classe de conexão dentro de app/channels/. Isso mantém os padrões limpos e coloca nossa lógica em um lugar claro.
# 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: Contadores na Memória
Usaremos contadores atômicos para tornar as coisas rápidas. Na inicialização, pegamos o total de visitas do DB e começamos a contagem de usuários online em zero.
# config/initializers/traffic_counter.rb
$online_users = Concurrent::AtomicFixnum.new(0)
$total_visits = Concurrent::AtomicFixnum.new(Visit.count)
Passo 4: O Canal
Aqui é onde a diversão acontece — registre a visita, atualize os contadores e transmita.
# app/channels/traffic_channel.rb
class TrafficChannel < ApplicationCable::Channel
def subscribed
# registrar visita
Visit.create!(session_id: connection.session_id,
ip: connection.ip,
user_agent: connection.user_agent)
# atualizar contadores
$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: O Lado do JavaScript
Quando você executa bin/rails generate channel Traffic, o Rails cria dois arquivos: o canal Ruby e o arquivo de assinatura JavaScript. Por padrão, o arquivo JS importa consumer.js, que o Rails também configurou para você quando o aplicativo foi gerado.
// 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
}
})
O arquivo consumer.js é gerado pelo Rails quando você cria um novo aplicativo. Ele configura a conexão global WebSocket para /cable e se parece com isso:
// app/javascript/channels/consumer.js
import { createConsumer } from "@rails/actioncable"
export default createConsumer()
Passo 6: A Visualização
<h1>🚦 Tráfego Ao Vivo</h1>
<p>Atualmente online: <span id="online-count">0</span></p>
<p>Total de visitas: <span id="total-count"><%= Visit.count %></span></p>
Passo 7: Rotas
# config/routes.rb
Rails.application.routes.draw do
root "home#index"
mount ActionCable.server => "/cable"
end
Passo 8: Experimente
Execute seu aplicativo com bin/dev. Abra seu site em algumas abas. O contador de usuários online aumenta com cada uma delas e diminui quando você as fecha. O total de visitas continua subindo. Super satisfatório de assistir!
Notas para Produção
- Múltiplos trabalhadores Puma? Use Redis para contadores — a memória não será sincronizada entre processos.
- Quer rastrear usuários reais em vez de sessões? Adicione current_user na conexão.
- Armazenar visitas no DB significa que você pode executar análises depois, como tráfego diário ou divisões de navegador.
E é isso — um contador de tráfego ao vivo em tempo real no Rails 7 com Action Cable. Em menos de 100 linhas de código, você tem atualizações instantâneas e um gostinho do que os WebSockets podem fazer. Essa mesma configuração funciona para notificações, painéis e todos os tipos de recursos em tempo real. Uma vez que você experimentou, vai querer espalhar isso por toda parte.