How To Create a Multi-Use Channel with Rails 5 Beta ActionCable
The highlight of rails 5, still in beta, is the introduction of ActionCable, which allows browsers across multiple users to communicate information nearly instantly. Imagine, for example, a board game where each users sees the board pieces respond as soon as the other player makes a move, or a group order that updates whenever a user adds an item, or a message room where users can see chats in real time. When one user does an action, the browsers for all users will show it without the page refresh.
Before Rails 5, this critical functionality could not be achieved natively within the Rails framework. It had to be forced in using third party code. With Rails 5, however, ActionCable will be merged in to work as elegantly as any other natural Rails capability.
How is ActionCable implemented? It uses a WebSocket protocol that, on initialization with a client, creates a connection between the client and the server, constantly updating all users whenever a change is communicated to the server. We developers enact these connections by creating ‘channels’ that carry out the tasks we want the WebSocket to accomplish. Thus, to take the examples from earlier, we might have a messaging channel, an item adding channel, and a game move channel.
But, using a switch statement, we can also create a single channel that can handle many different types of requests.
In my food ordering app, we wanted to create a single channel in a restaurant order show page where users could add and delete items to an order as well as chat with other users about the order. Other users would see items added to or deleted from the order and messages added to the chat as soon as they happened.
To get this dual functionality, we decided to create a single channel that could handle both tasks. By doing so, we also avoided some Rails 5′s bugs that can occur when multiple different channels are enacted, freezing the server. Rails 5, after all, is still in beta!
Take a look at controller for items and the controller for messages. Note that each time we broadcast to the server, one of the data params we pass in has a key of :action and a string as its value that describes the action of the broadcast.
app/assets/controllers/messages_controller.rb
app/assets/controllers/items_controller.rb
Saw the :action strings on lines 9 and 12, 30 respectively? They aren’t magic. Rather, they help operate a javascript switch statement that determines the response from our channel.
See below for the javascript:
app/assets/javascripts/channels/orders.js
There are three types of actions on the order show page that we want done by the channel. The first is to make a message appear in the chat column when a user creates a message (lines 4-7). The second is for an item to appear and the cost of an order to update when a user adds an item (lines 8-12). The third is for an item to disappear and the cost of an order to update if a user deletes the item (lines 13-17).
Take a look at the switch statement on line 3. We call .action on the data sent by the channel, which gives back one of the strings we sent through as the value of the action key (either add-message, add-item, or delete-item). Based on that string, different code is run. Though not all of the code for the different cases are included in the screenshot above, you can get a general sense of what the code does from the names of the functions.
POOF. By using a switch statement and passing through a string as part of data, we’ve efficiently added multiple capabilities to our order show page through the use of a single ActionCable channel.