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!