# Action Cable i WebSockety w Rails: Kompletny przewodnik na rozmowy techniczne 2026 > Dogłębna analiza Action Cable i WebSocketów w Ruby on Rails. Połączenia, kanały, broadcasting, Solid Cable w Rails 8, skalowanie z Redis oraz najczęstsze pytania na rozmowach kwalifikacyjnych z przykładami kodu. - Published: 2026-05-07 - Updated: 2026-05-07 - Author: Anthony Fillion-Maillet - Tags: ruby on rails, action cable, websockets, real-time, solid cable, rails 8 - Reading time: 11 min --- Action Cable wprowadza obsługę WebSocketów bezpośrednio do frameworka Rails, umożliwiając budowanie funkcjonalności czasu rzeczywistego — czatu, powiadomień czy dashboardów na żywo — bez zewnętrznych zależności. Na rozmowach technicznych w 2026 roku znajomość wewnętrznych mechanizmów Action Cable, od cyklu życia połączenia po skalowanie na produkcji, wyróżnia silnych kandydatów. > **Kluczowy wniosek na rozmowę** > > Action Cable integruje WebSockety z frameworkiem Rails, stosując te same konwencje co kontrolery i modele. Rails 8 wprowadza Solid Cable — adapter oparty na bazie danych, eliminujący konieczność korzystania z Redisa do obsługi pub/sub. ## Podstawy protokołu WebSocket w kontekście Rails Protokół WebSocket (RFC 6455) ustanawia trwałe, dwukierunkowe połączenie komunikacyjne przez pojedyncze połączenie TCP. W przeciwieństwie do cyklu żądanie-odpowiedź w HTTP, WebSockety utrzymują otwarte połączenie, w którym zarówno klient, jak i serwer mogą wysyłać wiadomości w dowolnym momencie. Action Cable opakowuje ten protokół w abstrakcję przyjazną dla Rails. Serwer obsługuje aktualizację połączenia do WebSocket pod adresem `/cable`, zarządza uwierzytelnianiem połączeń i kieruje wiadomości przez kanały. Biblioteka JavaScript po stronie klienta automatycznie tworzy i zarządza subskrypcjami. Typowe żądanie HTTP kończy się w milisekundach i zamyka połączenie. Połączenie WebSocket pozostaje otwarte przez minuty, godziny lub całą sesję użytkownika. Ta fundamentalna różnica determinuje każdą decyzję architektoniczną w Action Cable. ## Architektura Action Cable: połączenia, kanały i subskrypcje Action Cable stosuje warstwową architekturę z trzema głównymi abstrakcjami: połączenia obsługują uwierzytelnianie, kanały enkapsulują logikę biznesową, a subskrypcje łączą konsumentów z konkretnymi kanałami. ```ruby # 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 # Cookies are available in WebSocket handshake if verified_user = User.find_by(id: cookies.encrypted[:user_id]) verified_user else reject_unauthorized_connection end end end end ``` Klasa połączenia uruchamia się jednokrotnie przy handshaku WebSocket. Uwierzytelnianie odbywa się właśnie tutaj — nie w poszczególnych kanałach. Deklaracja `identified_by` rejestruje tożsamość użytkownika, udostępniając ją we wszystkich subskrypcjach kanałów w danym połączeniu. ```ruby # app/channels/chat_channel.rb class ChatChannel < ApplicationCable::Channel def subscribed room = ChatRoom.find(params[:room_id]) # Authorization: verify user belongs to this room 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 # Cleanup: mark user as offline AppearanceTracker.mark_offline(current_user) end end ``` Kanały definiują trzy callbacki cyklu życia: `subscribed`, `receive` i `unsubscribed`. Metoda `stream_for` wiąże subskrypcję z konkretną instancją modelu, tworząc strumień z przestrzenią nazw. Broadcasting do tego strumienia dostarcza wiadomości do każdego podłączonego subskrybenta. ## Subskrypcje po stronie klienta w JavaScript Konsument po stronie klienta łączy się z serwerem Action Cable i zarządza subskrypcjami. Każda subskrypcja odpowiada kanałowi po stronie serwera. ```javascript // app/javascript/channels/chat_channel.js import consumer from "./consumer" const chatChannel = consumer.subscriptions.create( { channel: "ChatChannel", room_id: roomId }, { connected() { // Called when the subscription is ready console.log("Connected to chat room", roomId) }, disconnected() { // Called when the subscription is closed console.log("Disconnected from chat room") }, received(data) { // Called when data is broadcast to the channel const messageList = document.getElementById("messages") messageList.insertAdjacentHTML("beforeend", `
` ) }, sendMessage(body) { // Calls ChatChannel#receive on the server this.perform("receive", { body: body }) } } ) ``` Callback `received` uruchamia się za każdym razem, gdy serwer broadcastuje do subskrybowanego strumienia. Metoda `perform` wysyła dane od klienta do serwera, wywołując odpowiednią metodę kanału. ## Solid Cable w Rails 8: pub/sub oparty na bazie danych Rails 8 wprowadza Solid Cable jako element "Solid Trifecta" obok Solid Queue i Solid Cache. Solid Cable zastępuje Redisa jako backend pub/sub, przechowując wiadomości w tabeli bazy danych. ```yaml # 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.day ``` Solid Cable działa poprzez zapis każdej wiadomości broadcast do tabeli bazy danych i odpytywanie o nowe wiadomości w konfigurowalnym interwale. Domyślny interwał 100ms zapewnia dostarczanie niemal w czasie rzeczywistym dla większości aplikacji. Kompromis jest jasny: Solid Cable eliminuje zależność infrastrukturalną (Redis) kosztem nieco wyższego opóźnienia i obciążenia bazy danych. Dla aplikacji już korzystających z PostgreSQL lub MySQL ten kompromis często ma sens. Przy wysoko-częstotliwościowym broadcastingu (tysiące wiadomości na sekundę) Redis pozostaje lepszym wyborem. ```ruby # config/database.yml (Rails 8 multi-database) production: primary: <<: *default database: myapp_production cable: <<: *default database: myapp_cable_production migrations_paths: db/cable_migrate ``` Solid Cable wykorzystuje dedykowaną bazę danych, aby uniknąć rywalizacji z bazą główną. To rozdzielenie zapobiega wpływowi odpytywania o wiadomości na zapytania aplikacji. ## Wzorce broadcastingu i triggery po stronie serwera Broadcasting z modeli, zadań w tle i kontrolerów obejmuje trzy najczęstsze wzorce w produkcyjnych aplikacjach Rails. ```ruby # 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 end ``` Callbacki modelu nadają się do prostych powiadomień wywoływanych zmianami rekordów. Zadania w tle obsługują cięższe obliczenia — wyliczanie statystyk dashboardu czy agregowanie danych — bez blokowania cyklu żądania. Sam broadcast jest zawsze lekki: serializuje payload i publikuje go do adaptera. ## Turbo Streams i integracja z Action Cable Rails 8 z Hotwire wykorzystuje Action Cable jako warstwę transportową dla Turbo Streams, umożliwiając aktualizacje DOM w czasie rzeczywistym bez pisania własnego JavaScriptu. ```ruby # app/models/message.rb class Message < ApplicationRecord belongs_to :chat_room # Automatically broadcasts append to subscribers broadcasts_to :chat_room end # app/views/chat_rooms/show.html.erb <%= turbo_stream_from @chat_room %>