Action Cable Rails ChatApp with React hooks

Saloni Mehta
6 min readDec 15, 2021

If you came across this article, you either have heard of Action Cable before or you are looking to dive in to learn about Action Cable and how you can use it in your project. I was in the same boat and went into this rabbit hole trying to find the best resources and reading different blog posts & eventually learning how this can work in my app. This blog post is going to be a long one because I would like to try to cover as much as possible.

As every project is different and you may have different ideas or things in place but I will try to help you get started if this is your first time using Action Cable. This is how my Project looks like

demo
Real-time Communication among chatroom subscribers

Action Cable allows for real-time features to be written in Ruby in the same style and form as the rest of your Rails application, while still being performant and scalable. Action Cable uses WebSockets instead of the HTTP request-response protocol. Both Action Cable and WebSockets introduce some less familiar terminology. It’s recommended to read into rails guide to get yourself familiar with the terminology as it will make sense with the rest of the blog post. https://guides.rubyonrails.org/action_cable_overview.html#terminology

What is WebSockets?

WebSocket is a two-way computer communication protocol over a single TCP. This is a common definition for it. Using WebSockets is a good way to handle high-scale data transfers between server clients. We will use WebSockets instead of HTTP for our app as it supports full-duplex Communication faster.

more on WebSockets https://en.wikipedia.org/wiki/WebSocket

drew using https://excalidraw.com

Let’s start with the relationship among my models and how I structured it before starting the project

Controllers used are :- MessagesController, UsersController ChatroomController, SessionsController (for authentication/authorization)

Now, to create ActionCable Connection I first had to create a route in my routes.rb

and in Cable.yml file change the adapter to redis and uncomment the redis gem from gemfile and then bundle install to install redis gem

Action Cable uses Redis to send and receive messages over the channel. So, when we told our Action Cable server to #broadcast to ‘messages’, we were saying “send new messages to the ‘messages’ channel maintained by Redis.”

next, in our channels/application_cable, we have connection.rb, where we are going to set up the WebSocket connection.

I have some byebug placements for checking the connection with my frontend react

For every WebSocket accepted by the server, a connection object is instantiated and its sole job is to authenticate and authorize the current user.

Next, we are going to create the Chatrooms Channel which will do the job of broadcasting our messages to all the users in that channel because they are technically subscribed to the same channel when that WebSocket connection is established.

this is how my ChatroomsChannel looks like

Okay, I know this can look confusing but what we are trying to do here is in our subscribed method we are going to find the chatroom, and then we are streaming for that chatroom which means after the connection is established our frontend will create the connection and send that to backend and then our backend will stream on that channel live

in our received method we are receiving data from our frontend to broadcast and using ChatroomsChannel.broadcast_to we are broadcasting the information we sent from frontend to all the users.

how would that work in our messages controller?

in our messages controller, I have a create method that when that message gets created it broadcasts to ChatroomsChannel.

now before we proceed to set up the connection with react we need to make sure that data we receive from the backend is how we are going to structure it in our frontend as well.

I used the fastJsonapi for the serializer, it converts JSON data to serializable hash

now let’s move to frontend to create the cable connection

in our index.js import actionCable from ‘actioncable’ , you will have to install the actioncable package do- npm i actioncable on your client-side

cableApp.cable=actionCable.createConsumer(‘ws://localhost:3000/cable’). This will create a new consumer (every subscription to a channel needs consumers to be subscribed to it )and notice we didn’t use HTTP here, instead we are using WebSocket to have that faster full-duplex connection.

Now we have established the 1st step to create a consumer we are going to pass down this cableApp to our main App component as it will be used later to send the data to the backend.

we will create a component that will Subscribe the consumer to the Chatrooms Channel and the room here will have the id, if you remember below we tried to find the chatroom by room params this is where that room is coming from

The updateApp and getRoomData methods are the methods that are getting the room information and one is updating on the client state for the current rooms data but also with that sending the information to the backend

These are the methods I have in my App.js and they are being passed down to the component <RoomShow> which shows an individual chatroom that then have the <RoomWebSocket> component but its only sole purpose is to create the subscription so it just exists in the <RoomShow> like this

and that’s it, now you can submit your messages and they will be broadcasted to every person in the channel and you can have real-time communication.

Bonus: you can add update and destroy options to your project as I did

Once I updated it, it broadcasted the changes to all the users that are subscribed to the channel. I could also delete a message and that also got updated in real-time.

to make this achievable I made some changes to my messages controller as follows. I created a private method broadcast that takes the current chatroom as an argument and broadcasts for that channel and called that method inside my update, destroy methods as well for the changes to be broadcasted.

and that’s it. now you have a fully functioning Action cable chat app with all the necessary chat features.

There were very limited resources on Action Cable using React Hooks when I was trying to learn Action Cable, it can sure seem like a challenge when you first come across it but once you see how great it can be, I would say that challenge is worth it!

--

--