Getting started with Rails 5's ActionCable and websockets

17 Jul 2015

ActionCable is the websockets framework that ships with Rails 5.
It aims to simplify the addition of realtime features to Rails apps.
In this tutorial, we will explore ActionCable by
building a simple chat application.

Let’s get started by installing the pre-release version of Rails (5.0.0.beta).
Once the final 5.0.0 version of Rails is released,
we won’t have to add the --pre flag to the gem install command.

gem install rails --pre
rails new chatter --skip-spring

(ActionCable isn’t working well with Spring in 5.0.0.beta1,
which is why I’m using the --skip-spring option.
This should be fixed in future versions of Rails.)

Adding the views

We will be displaying the chat messages in messages#index.
Before joining the chat room, we will ask users to set a username
that will be displayed along with the chat messages.
The sessions#new view will contain the form to pick a username,
and we will also set it as the home page.
Let’s add these routes to routes.rb:

Next, we add a SessionsController.
The #new method only renders a view, so we can omit it here,
and just add the view template.
The #create method sets a signed cookie, username
that we will use to identify the user.

When a client connects to the channel, the #subscribed action is called.
This subscribes the client to a stream called messages.
Whenever data is broadcast to the messages stream, it is pushed to the clients.

The #speak action corresponds to a method in the client side code.
When a user types a message a hits enter, we can call App.chat.speak
on the client side, which in turn invokes this action on the server.

When we receive a message in the #speak action,
we will render the HTML for that message to the messages stream.
We’re using the newly introduced ApplicationController.render method
which allows us to render a partial into a string.
Let’s create the partial:

app/views/messages/_message.html.erb:

<p><%=message%></p>

When we broadcast the HTML to the messages stream,
all the clients connected to the channel will receive the data
and call the App.chat.received method on the client side.

Nest stop: writing the client side code corresponding to this.

Client side code

Update:
This code uses jquery,
which is not included by default
in Rails 5.1 and above.
Refer to Adam Narel’s comment below
on how to include jquery.

Rails has already generated some client side code for us.
Let’s start by handling the event when enter is pressed in the chat input field.
Add this at the end of app/assets/javascripts/channels/chat.coffee:

With this, our chat app is ready.
Try submitting a message in the input field,
and you’ll see it appear on the page.
There is one problem with this, though.
We aren’t showing the name of the person sending the message.
Let’s fix that.

Setting current_user

In the messages/_message partial, we want to be able to
access the username of the current user.
To do this, we will add a #current_user method in
ApplicationCable::Connection.

If you want to look at how similar features are implemented
in other languages and frameworks,
I recently wrote about building a similar
chat app using the Phoenix framework
for the Elixir language.
Because of Elixir’s similarity with Ruby in terms of syntax,
it should be easy for Rubyists to follow along.

Hi, I’m Nithin Bekal.
I work at Shopify in Ottawa, Canada.
Previously, co-founder of
CrowdStudio.in and
WowMakers.
Ruby is my preferred programming language,
and the topic of most of my articles here,
but I'm also a big fan of Elixir.
Tweet to me at @nithinbekal.