Introduction

Today we will be taking a look at how you might go about implementing a real-time messaging system in your Ruby on Rails back end.

Contrary to what many newcomers to programming would be forgiven for thinking, this is actually a relatively straightforward task.

Before starting this, you will need to ensure that you have the redis gem installed. Once you’ve installed it, don’t forget to run the bundle install command.

Server-side code

Configuring Action Cable is a simple process, so we will skip this part in today’s article. If you are unsure of how to do this, there are a multitude of online articles which explain this.

The first step involves creating a channels directory inside the main app directory of your Rails project. This will house the channels that will be used to pass through new data in real time.

Our setup relies on two channels: a conversations channel and a messages channel.

Conversations channel

class ConversationsChannel < ApplicationCable::Channel
  def subscribed
    stream_from "conversations_channel"
  end

  def unsubscribed
    # Add any code to run when channel is unsubscribed
  end
end

Messages channel

class MessagesChannel < ApplicationCable::Channel
  def subscribed
    conversation = Conversation.find(params[:conversation])
    stream_for conversation
  end

  def unsubscribed
    # Add any code to run when channel is unsubscribed
  end
end

These channels are used to keep an open connection for the transmission of data between our back end and front end.

Client-side code

For this next part, we assume that you have already configured your models for both the conversation and message part of the chat system. If not, the following points should help you get started on that before following up with this section.

  • A conversation has many messages
  • A message belongs to a conversation
  • A message also belongs to a user

Of course, the finer points of this section are highly dependent on the front end that you are using. In our case, that is React Native, so we are using the react-native-actioncable NPM package.

In the section of your project where you wish to create an open connection, initialise an Action Cable consumer. We did this like so:

const cable = ActionCable.createConsumer('https://name-of-your-api.com/cable')
cable.connect()

Please note that the cable end point is something you should have configured within your Rails back end.

Next, we need to prime our consumer to subscribe to changes on the channel of our choosing. In this example we will focus on the Messages Channel detailed above. The code looks something like this:

  this.messages = cable.subscriptions.create({
     channel: 'MessagesChannel',
     conversation: conversation_id
   }, {
     connected: () => {console.log("Connected to action cable socket");
},
     received: (data) => {
       console.log('New message: ', data.message)
       // Whatever you wish to do with the data
     }
   })

Our Rails server expects to receive the ID of a conversation object so that it can relay new data (i.e. messages) from that conversation to the client.

Assuming the conversation ID is valid, we will now have an open channel of communication around which we can start building the basis of an interactive modern messaging system.


If you have any feedback or suggestions, feel free to reach out to us on Twitter. Thanks!