Getting started with Rails 5's ActionCable and websockets
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.
(ActionCable isn’t working well with Spring in 5.0.0.beta1,
which is why I’m using the
This should be fixed in future versions of Rails.)
Adding the views
We will be displaying the chat messages in
Before joining the chat room, we will ask users to set a username
that will be displayed along with the chat messages.
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.
#new method only renders a view, so we can omit it here,
and just add the view template.
#create method sets a signed cookie,
that we will use to identify the user.
We’ll also add the erb template for
#index method only renders the view,
so we don’t need to do anything there:
messages/index template looks like this:
#messages div is where we’ll append
all the chat messages coming through the channel.
Adding a channel
The next thing we will do is generate a channel that we can use to communicate via websockets between the client and the server.
This will generate a
ChatChannel with an action called
It also generates a
chat.coffee file in
After creating our first channel, we need to turn on the cable connection in
by uncommenting these lines:
We also need to uncomment a line in
config/routes.rb so that
ActionCable runs in the same process when we run
First, we need to handle the actions present in
When a client connects to the channel, the
#subscribed action is called.
This subscribes the client to a stream called
Whenever data is broadcast to the messages stream, it is pushed to the clients.
#speak action corresponds to a method in the client side code.
When a user types a message a hits enter, we can call
on the client side, which in turn invokes this action on the server.
When we receive a message in the
we will render the HTML for that message to the
We’re using the newly introduced
which allows us to render a partial into a string.
Let’s create the partial:
When we broadcast the HTML to the
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
When you hit enter in the
#chat-speak input field,
this pushes the content of the field to the chat channel
App.chat.speak, which in turn sends it to the cable server.
Let’s also handle the two main actions in
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.
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
The next thing to do is to use this
Restart the rails server and open the chat in two different browsers. Now, you can see the messages being rendered with the username.
- Code for this example
- ActionCable screencast by DHH
- ActionCable examples from the Rails core team have some very nice examples that show off the more advanced features of ActionCable.
- GoRails: ActionCable and Websockets Introduction explores the code from the ActionCable examples linked above in a great screencast.
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.