# Action Cable dan WebSockets di Rails: Panduan Lengkap untuk Wawancara Teknis > Panduan lengkap Action Cable dan WebSockets di Rails untuk persiapan wawancara teknis. Mencakup arsitektur, Solid Cable, Turbo Streams, dan pola scaling. - Published: 2026-05-07 - Updated: 2026-05-07 - Author: Anthony Fillion-Maillet - Tags: action-cable, websockets, rails, real-time, solid-cable - Reading time: 12 min --- Komunikasi real-time telah menjadi fitur yang sangat penting dalam aplikasi web modern. Mulai dari fitur chat, notifikasi langsung, hingga pembaruan dashboard secara otomatis, pengguna mengharapkan pengalaman yang responsif tanpa perlu memuat ulang halaman. Action Cable, yang merupakan framework bawaan Rails untuk WebSockets, menyediakan solusi terintegrasi yang memungkinkan pengembang membangun fitur-fitur tersebut dengan mengikuti konvensi Rails yang sudah familiar. > **Poin Penting untuk Wawancara** > > Action Cable menjembatani komunikasi WebSocket dengan arsitektur Rails yang sudah ada, sehingga memungkinkan pengembangan fitur real-time menggunakan pola yang konsisten dengan bagian aplikasi Rails lainnya. Rails 8 memperkenalkan Solid Cable, adapter berbasis database yang mengeliminasi kebutuhan akan Redis untuk pub/sub messaging. ## Dasar-Dasar Protokol WebSocket Protokol WebSocket menyediakan saluran komunikasi full-duplex melalui koneksi TCP tunggal. Berbeda dengan model request-response tradisional HTTP, WebSocket mempertahankan koneksi persisten yang memungkinkan server dan klien untuk saling mengirim data kapan saja. Proses ini dimulai dengan HTTP handshake yang kemudian di-upgrade menjadi koneksi WebSocket. Perbedaan mendasar antara HTTP dan WebSocket terletak pada sifat koneksinya. HTTP bersifat stateless dan unidirectional, di mana klien harus selalu menginisiasi request. Sebaliknya, WebSocket bersifat stateful dan bidirectional, memungkinkan komunikasi dua arah secara simultan. Karakteristik ini membuat WebSocket sangat cocok untuk aplikasi yang membutuhkan pembaruan data secara real-time. Dalam konteks Rails, Action Cable mengabstraksi kompleksitas manajemen koneksi WebSocket, sehingga pengembang dapat fokus pada logika bisnis aplikasi tanpa harus menangani detail teknis protokol secara langsung. ## Arsitektur Action Cable Action Cable terdiri dari tiga komponen utama: connections, channels, dan subscriptions. Pemahaman mendalam tentang ketiga komponen ini sangat penting untuk membangun fitur real-time yang robust dan scalable. ### Connections Connection merepresentasikan koneksi WebSocket individual antara klien dan server. Setiap connection dapat diidentifikasi berdasarkan pengguna yang terautentikasi, memungkinkan pengiriman pesan yang ditargetkan kepada pengguna tertentu. ```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 ``` Kode di atas mendemonstrasikan bagaimana autentikasi ditangani pada level connection. Method `find_verified_user` mengakses cookies yang tersedia selama WebSocket handshake untuk memverifikasi identitas pengguna. Jika pengguna tidak terautentikasi, koneksi akan ditolak dengan `reject_unauthorized_connection`. ### Channels Channel berfungsi sebagai unit logis untuk mengorganisasi fitur real-time. Setiap channel menangani jenis komunikasi tertentu, seperti chat, notifikasi, atau pembaruan dashboard. Pendekatan ini mengikuti prinsip separation of concerns yang menjadi fondasi arsitektur Rails. ```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 ``` Implementasi ChatChannel di atas menunjukkan beberapa konsep penting. Method `subscribed` menangani otorisasi dengan memverifikasi bahwa pengguna merupakan anggota chat room. Method `receive` memproses pesan masuk dari klien dan melakukan broadcast ke semua subscriber. Method `unsubscribed` menjalankan cleanup logic ketika koneksi terputus. Penggunaan `stream_for` dengan model object memungkinkan Action Cable untuk secara otomatis mengelola nama stream berdasarkan class dan ID model. Pola ini menyederhanakan manajemen stream dan mengurangi kemungkinan kesalahan dalam penamaan. ## Subscriptions di Sisi Klien Integrasi sisi klien menggunakan JavaScript untuk membuat dan mengelola subscriptions ke channels. Rails menyediakan consumer object yang menangani koneksi WebSocket dan menyediakan API untuk berinteraksi dengan server. ```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 }) } } ) ``` Kode JavaScript di atas mendemonstrasikan lifecycle lengkap subscription. Callback `connected` dipanggil ketika subscription berhasil dibuat, `disconnected` ketika koneksi terputus, dan `received` ketika data diterima dari server. Method `sendMessage` menunjukkan bagaimana klien dapat mengirim data ke server menggunakan `this.perform`. Pola ini memisahkan concerns dengan jelas: server menangani logika bisnis dan persistensi data, sementara klien menangani rendering dan interaksi pengguna. ## Solid Cable di Rails 8 Rails 8 memperkenalkan Solid Cable sebagai adapter default untuk Action Cable. Solid Cable menyimpan messages di database relasional menggunakan polling yang dioptimalkan, mengeliminasi kebutuhan akan Redis untuk banyak kasus penggunaan. Pendekatan ini menyederhanakan infrastruktur deployment tanpa mengorbankan performa secara signifikan untuk aplikasi skala kecil hingga menengah. ```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 ``` Konfigurasi di atas menunjukkan setup Solid Cable untuk development dan production. Perhatikan penggunaan `connects_to` yang memungkinkan Solid Cable menggunakan database terpisah untuk operasi cable, mencegah interferensi dengan database utama aplikasi. ```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 ``` Konfigurasi multi-database ini memisahkan storage untuk cable messages dari database utama. Pemisahan ini memberikan beberapa keuntungan: mengurangi beban pada database utama, memungkinkan scaling independen, dan menyederhanakan manajemen retensi data untuk messages yang bersifat ephemeral. Solid Cable cocok untuk aplikasi dengan ratusan hingga ribuan koneksi simultan. Untuk aplikasi dengan skala yang lebih besar, Redis tetap menjadi pilihan yang direkomendasikan karena karakteristik performa yang lebih superior untuk operasi pub/sub. ## Pola Broadcasting Broadcasting merupakan mekanisme untuk mengirim data dari server ke semua subscribers yang relevan. Rails menyediakan beberapa pola untuk melakukan broadcast, masing-masing dengan trade-offs tersendiri. ```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 ``` Kedua pola di atas mendemonstrasikan pendekatan yang berbeda untuk broadcasting. Model callback cocok untuk broadcast yang langsung terkait dengan perubahan data, memastikan konsistensi antara state database dan notifikasi real-time. Background job lebih tepat untuk operasi yang membutuhkan komputasi intensif atau tidak perlu blocking. Penggunaan `after_create_commit` alih-alih `after_create` sangat penting untuk memastikan bahwa broadcast hanya terjadi setelah transaksi database berhasil di-commit. Pola ini mencegah race condition di mana klien menerima notifikasi tentang data yang belum tersedia di database. ## Integrasi Turbo Streams Turbo Streams, bagian dari Hotwire, menyediakan abstraksi tingkat tinggi untuk broadcasting DOM updates. Integrasi ini memungkinkan pengembang untuk membangun fitur real-time dengan kode minimal, mengikuti prinsip convention over configuration. ```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 %>