# Action Cable та WebSocket у Rails: Повний посібник для технічних співбесід 2026 > Поглиблений аналіз Action Cable та WebSocket у Ruby on Rails. З'єднання, канали, broadcasting, Solid Cable у Rails 8, масштабування з Redis та типові питання на співбесідах із прикладами коду. - 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 додає підтримку WebSocket безпосередньо у фреймворк Rails, дозволяючи створювати функції реального часу — чат, сповіщення, живі дашборди — без зовнішніх залежностей. На технічних співбесідах 2026 року знання внутрішніх механізмів Action Cable, від життєвого циклу з'єднання до масштабування у продакшені, відрізняє сильних кандидатів від решти. > **Ключовий висновок для співбесіди** > > Action Cable інтегрує WebSocket у фреймворк Rails з тими ж конвенціями, що використовуються для контролерів і моделей. Rails 8 представляє Solid Cable — адаптер на основі бази даних, що усуває потребу в Redis для pub/sub-повідомлень. ## Основи протоколу WebSocket у контексті Rails Протокол WebSocket (RFC 6455) встановлює постійний, повнодуплексний канал зв'язку через одне TCP-з'єднання. На відміну від циклу запит-відповідь у HTTP, WebSocket підтримує відкрите з'єднання, де як клієнт, так і сервер можуть надсилати повідомлення у будь-який момент. Action Cable обгортає цей протокол у зручну для Rails абстракцію. Сервер обробляє оновлення з'єднання до WebSocket за адресою `/cable`, керує автентифікацією з'єднань та маршрутизує повідомлення через канали. Клієнтська бібліотека JavaScript автоматично створює та керує підписками. Типовий HTTP-запит завершується за мілісекунди та закриває з'єднання. З'єднання WebSocket залишається відкритим хвилини, години або протягом усієї сесії. Ця фундаментальна різниця визначає кожне архітектурне рішення в Action Cable. ## Архітектура Action Cable: з'єднання, канали та підписки Action Cable дотримується багатошарової архітектури з трьома основними абстракціями: з'єднання обробляють автентифікацію, канали інкапсулюють бізнес-логіку, а підписки зв'язують споживачів із конкретними каналами. ```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 ``` Клас з'єднання виконується один раз під час рукостискання WebSocket. Автентифікація відбувається саме тут — не в окремих каналах. Оголошення `identified_by` реєструє ідентичність користувача, роблячи її доступною у всіх підписках каналів цього з'єднання. ```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 ``` Канали визначають три callback-и життєвого циклу: `subscribed`, `receive` та `unsubscribed`. Метод `stream_for` прив'язує підписку до конкретного екземпляра моделі, створюючи потік з простором імен. Broadcasting до цього потоку доставляє повідомлення кожному підключеному підписнику. ## Підписки на стороні клієнта у JavaScript Клієнтський consumer підключається до сервера Action Cable та керує підписками. Кожна підписка відповідає каналу на стороні сервера. ```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` спрацьовує щоразу, коли сервер виконує broadcast до підписаного потоку. Метод `perform` надсилає дані від клієнта до сервера, викликаючи відповідний метод каналу. ## Solid Cable у Rails 8: pub/sub на основі бази даних Rails 8 представляє Solid Cable як частину "Solid Trifecta" разом із Solid Queue та Solid Cache. Solid Cable замінює Redis як бекенд pub/sub, зберігаючи повідомлення у таблиці бази даних. ```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 працює шляхом запису кожного broadcast-повідомлення у таблицю бази даних та опитування нових повідомлень із налаштовуваним інтервалом. Стандартний інтервал опитування 100 мс забезпечує доставку майже в реальному часі для більшості застосунків. Компроміс очевидний: Solid Cable усуває інфраструктурну залежність (Redis) ціною дещо більшої затримки та навантаження на базу даних. Для застосунків, що вже використовують PostgreSQL або MySQL, цей компроміс часто виправданий. Для високочастотного broadcasting (тисячі повідомлень за секунду) Redis залишається кращим вибором. ```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 використовує виділену базу даних, щоб уникнути конкуренції з основною базою. Це розділення запобігає впливу опитування повідомлень на запити застосунку. ## Патерни broadcasting та тригери на стороні сервера Broadcasting з моделей, фонових завдань та контролерів охоплює три найпоширеніші патерни у продакшн-застосунках 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 ``` Callback-и моделей підходять для простих сповіщень, що викликаються змінами записів. Фонові завдання обробляють важчі обчислення — розрахунок статистики дашборду чи агрегацію даних — без блокування циклу запиту. Сам broadcast завжди легкий: він серіалізує payload та публікує його до адаптера. ## Turbo Streams та інтеграція з Action Cable Rails 8 із Hotwire використовує Action Cable як транспортний рівень для Turbo Streams, забезпечуючи оновлення DOM у реальному часі без написання власного JavaScript. ```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 %>