# 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", `
${data.user}: ${data.body}
` ) }, 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 %>
<%= render @chat_room.messages %>
``` Dengan `broadcasts_to`, Rails secara otomatis melakukan broadcast Turbo Stream frames ketika model dibuat, diupdate, atau dihapus. Helper `turbo_stream_from` di view membuat subscription ke channel yang sesuai dan menangani rendering updates secara otomatis. Pendekatan deklaratif ini secara signifikan mengurangi boilerplate code. Pengembang tidak perlu menulis JavaScript untuk handling DOM updates atau mendefinisikan channel classes untuk kasus penggunaan standar. Namun, untuk kebutuhan yang lebih kompleks, pendekatan manual tetap tersedia dan dapat dikombinasikan dengan Turbo Streams. ## Scaling di Production Untuk aplikasi dengan traffic tinggi, arsitektur Action Cable perlu dipertimbangkan dengan cermat. Setiap koneksi WebSocket mempertahankan state di server, yang berbeda dari model stateless HTTP tradisional. ```ruby # config/cable.yml — Redis adapter for high-scale production production: adapter: redis url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> channel_prefix: myapp_production ``` Redis adapter merupakan pilihan standar untuk production deployment dengan skala besar. Redis menyediakan pub/sub yang efisien dengan latency rendah, memungkinkan multiple Rails processes atau servers untuk berbagi channel subscriptions. Beberapa pertimbangan penting untuk scaling Action Cable meliputi pengelolaan connection pooling, implementasi health checks untuk WebSocket connections, dan strategi reconnection yang robust di sisi klien. Penggunaan load balancer yang mendukung WebSocket connections juga merupakan keharusan, dengan sticky sessions sebagai pendekatan yang umum digunakan. Monitoring merupakan aspek kritis dalam production deployment. Metrik seperti jumlah koneksi aktif, message throughput, dan latency perlu dipantau untuk mengidentifikasi bottlenecks dan merencanakan capacity planning. > **Wawasan Wawancara** > > Dalam wawancara teknis, pemahaman tentang trade-offs antara Solid Cable dan Redis, serta kemampuan untuk menjelaskan strategi scaling, menunjukkan pengetahuan yang mendalam tentang sistem production. ## Testing Channels Rails menyediakan testing framework yang komprehensif untuk Action Cable channels. Testing memastikan bahwa authorization logic, broadcast behavior, dan subscription lifecycle berfungsi sesuai ekspektasi. ```ruby # test/channels/chat_channel_test.rb require "test_helper" class ChatChannelTest < ActionCable::Channel::TestCase test "subscribes to a valid room" do room = chat_rooms(:general) user = users(:alice) stub_connection current_user: user subscribe room_id: room.id assert subscription.confirmed? assert_has_stream_for room end test "rejects subscription for unauthorized user" do room = chat_rooms(:private) user = users(:outsider) stub_connection current_user: user subscribe room_id: room.id assert subscription.rejected? end test "broadcasts messages to room subscribers" do room = chat_rooms(:general) stub_connection current_user: users(:alice) subscribe room_id: room.id assert_broadcast_on(room, hash_including(body: "Hello")) do perform :receive, body: "Hello" end end end ``` Test cases di atas mencakup tiga skenario penting: subscription yang valid, rejection untuk unauthorized user, dan verifikasi broadcast behavior. Helper `stub_connection` memungkinkan setup connection state tanpa actual WebSocket connection. Assertion seperti `assert_has_stream_for` dan `assert_broadcast_on` menyediakan cara ekspresif untuk memverifikasi behavior. Testing channel behavior secara terpisah dari integration tests memungkinkan feedback loop yang lebih cepat selama development dan membantu mengidentifikasi regressions dengan lebih presisi. ## Pertanyaan Wawancara Umum Beberapa pertanyaan yang sering muncul dalam wawancara teknis terkait Action Cable dan WebSockets meliputi penjelasan perbedaan antara HTTP polling, long polling, Server-Sent Events, dan WebSockets. Kandidat diharapkan dapat menjelaskan bagaimana Action Cable menangani autentikasi dan otorisasi pada koneksi WebSocket, serta mendeskripsikan arsitektur internal Action Cable termasuk connections, channels, dan subscriptions. **Bagaimana Action Cable mengautentikasi koneksi?** Autentikasi terjadi di `ApplicationCable::Connection#connect` selama WebSocket handshake. Cookies dari HTTP session tersedia pada tahap ini. Autentikasi berbasis token dapat dilakukan dengan mengirim token sebagai query parameter pada URL WebSocket. **Apa yang terjadi ketika koneksi WebSocket terputus?** Library klien Action Cable mengimplementasikan reconnection otomatis dengan exponential backoff. Di sisi server, callback `unsubscribed` dipanggil untuk setiap channel yang disubscribe oleh koneksi tersebut. **Kapan sebaiknya menggunakan Solid Cable dibanding Redis?** Solid Cable cocok untuk aplikasi dengan kebutuhan real-time moderat (di bawah 100 pesan per detik) yang ingin menghindari infrastruktur Redis tambahan. Redis tetap diperlukan untuk skenario high-throughput atau ketika latency di bawah 10ms menjadi keharusan. > **Kesalahan Umum** > > Menempatkan logika otorisasi di connection class alih-alih di channel individual merupakan kesalahan umum. Connection menangani autentikasi identitas (siapa pengguna ini?). Channel menangani otorisasi akses (apakah pengguna ini berhak mengakses room ini?). Mencampurkan tanggung jawab ini dapat menimbulkan celah keamanan. ## Kesimpulan - WebSocket menyediakan komunikasi full-duplex yang berbeda dari model request-response HTTP tradisional - Action Cable terdiri dari tiga komponen utama: connections untuk autentikasi, channels untuk logika bisnis, dan subscriptions untuk manajemen client-side - Rails 8 memperkenalkan Solid Cable sebagai alternatif Redis yang lebih sederhana untuk deployment skala kecil hingga menengah - Turbo Streams menyediakan abstraksi deklaratif untuk broadcasting DOM updates dengan boilerplate minimal - Testing channel behavior secara terpisah memungkinkan verifikasi authorization dan broadcast logic yang lebih presisi - Scaling membutuhkan pertimbangan tentang adapter choice, connection management, dan monitoring - [Latih pertanyaan wawancara Action Cable & WebSockets](/id/technologies/ruby-on-rails/interview-questions/action-cable-websockets) untuk memperkuat pemahaman konsep-konsep ini --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/id/blog/ruby-on-rails/action-cable-websockets-complete-guide