Rails Real Time using ActionCable

Rails Real Time using ActionCable

ActionCable is a component of the Rails framework that provides real-time communication capabilities using WebSockets—a protocol that provides two-way communication between the client and the server. This tutorial will guide you on how to use ActionCable to build a real-time application with a public chatroom example.

Table of Contents

Getting started

Before we start, make sure that:

  1. You have the latest version of Rails installed. If not, you can install it with:

    gem install rails
    
  2. You have Redis installed and running in your local machine since ActionCable uses Redis as a pub/sub service for real-time features.

    brew install redis
    redis-server /usr/local/etc/redis.conf
    
  3. Your environment can handle the WebSocket protocol.

Setting Up Your Rails Application

Start by creating a new Rails application:

rails new chatroom
cd chatroom

Next, we need to configure the cable adapter to use Redis. Open up config/cable.yml and set the development configuration:

development:
  adapter: redis
  url: redis://localhost:6379/1
  channel_prefix: chatroom_development

Creating the Chatroom Channels

Channels are the means through which messages are delivered in ActionCable. They act like controllers in the MVC architecture except that they work on a many-to-one basis.

You can generate a new channel using the Rails generator:

rails generate channel Chatroom

This will generate several files including app/channels/chatroom_channel.rb. Update chatroom_channel.rb to subscribe to a stream:

class ChatroomChannel < ApplicationCable::Channel
  def subscribed
    stream_from "chatroom_channel"
  end

  def unsubscribed
    # Any cleanup needed when the channel is unsubscribed
  end 
end

Broadcasting Messages

To broadcast a message to a particular stream, two steps are required:

  1. Define an action in the channel that broadcasts a message to its stream.
  2. Call that action via a client-side method.

Inside chatroom_channel.rb, let's add a speak method:

class ChatroomChannel < ApplicationCable::Channel
  def speak(data)
    ActionCable.server.broadcast 'chatroom_channel', message: data['message']
  end
end

Receiving Messages

We will create a new JavaScript function that listens for the received event in app/assets/javascripts/channels/chatroom.js:

App.chatroom = App.cable.subscriptions.create("ChatroomChannel", {
  connected: function() {},
  disconnected: function() {},
  received: function(data) {
    alert(data['message']);
  },
  speak: function(message) {
    return this.perform('speak', {
      message: message
    });
  }
});

Finalizing the Public Chatroom

Now, we can update the view and make the channel functional.

<input id="chat-input" type="text">
<button id="send-btn">Send</button>

<script>
  document.getElementById("send-btn").addEventListener('click', function() {
    App.chatroom.speak(document.getElementById('chat-input').value);
  });
</script>

Common Issues & Solutions

If your ActionCable application runs into issues, try the following:

Using ActionCable can seem daunting at first, but once set up, it's a powerful tool for creating real-time features in a Rails app.