February 20, 2023
ActionCable is a powerful feature in Ruby on Rails that allows developers to build real-time web applications using WebSockets. With ActionCable, you can create channels that handle bidirectional communication between the client and the server in real time. This tutorial will provide an introduction to ActionCable and guide you through creating a simple chat application.
Step 1: Create a new Rails app and install the necessary dependencies
First, create a new Rails app with the --api
flag to generate an API-only application:
rails new chat_app --api
Then, add the necessary gems to the Gemfile
:
# Gemfile
gem 'rack-cors'
gem 'redis'
gem 'redis-rails'
gem 'puma'
Install the gems:
bundle install
Step 2: Create a new React app using create-react-app
Next, create a new React app inside the Rails app using create-react-app
:
cd chat_app
npx create-react-app client
This will create a new React app inside the client
directory.
Step 3: Set up CORS and configure Redis for ActionCable
To allow Cross-Origin Resource Sharing (CORS) between the Rails server and the React client, add the following code to config/initializers/cors.rb
:
# config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins '*'
resource '*', headers: :any, methods: [:get, :post, :put, :patch, :delete, :options, :head], expose: ['access-token', 'expiry', 'token-type', 'uid', 'client']
end
end
Also, configure Redis for ActionCable in config/cable.yml
:
# config/cable.yml
development:
adapter: redis
url: redis://localhost:6379/1
Step 4: Create a new channel
Create a new channel called chat_channel
using the Rails generator:
rails generate channel Chat
This will create a new chat_channel.rb
file in app/channels
with the following code:
# app/channels/chat_channel.rb
class ChatChannel < ApplicationCable::Channel
def subscribed
stream_from "chat_channel"
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
end
This channel subscribes to the chat_channel
stream and defines the subscribed
method to stream messages from this channel.
Step 5: Update the routes.rb
file
Add the following code to config/routes.rb
:
# config/routes.rb
Rails.application.routes.draw do
resources :chat_rooms, only: [:index, :create]
mount ActionCable.server => '/cable'
end
This code sets up the routes for the chat rooms and mounts the ActionCable server at the /cable
endpoint.
Step 6: Create a new controller
Create a new controller called chat_rooms_controller.rb
:
rails generate controller ChatRooms index create
This will create a new chat_rooms_controller.rb
file in app/controllers
with the following code:
# app/controllers/chat_rooms_controller.rb
class ChatRoomsController < ApplicationController
def index
@messages = Message.all
end
def create
ActionCable.server.broadcast "chat_channel", message: params[:message], user: "anonymous"
Message.create(content: params[:message], user: "anonymous")
redirect_to chat_rooms_path
end
This controller defines the index
method to display the chat room and the create
method to broadcast the new message to the chat_channel
stream and create a new Message
object.
Step 7: Update the App.js
file in the React client
In the React client, update the App.js
file in the src
directory with the following code:
import React, { useState, useEffect } from 'react';
import logo from './logo.svg';
import './App.css';
import ChatRoom from './ChatRoom';
import ActionCableConsumer from 'react-actioncable-provider';
function App() {
const [messages, setMessages] = useState([]);
useEffect(() => {
fetch('/chat_rooms')
.then(response => response.json())
.then(data => setMessages(data));
}, []);
const handleReceivedMessage = (response) => {
setMessages([...messages, response]);
}
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1>React + Rails Chat App</h1>
</header>
<div className="Chat-room">
<ActionCableConsumer
channel={{ channel: 'ChatChannel' }}
onReceived={handleReceivedMessage}
/>
<ChatRoom messages={messages} />
</div>
</div>
);
}
export default App;
This code sets up the App
component to fetch the initial list of messages from the server and render a ChatRoom
component with an ActionCableConsumer
to listen for new messages.
Step 8: Create a new ChatRoom
component
Create a new ChatRoom.js
file in the src
directory with the following code:
import React, { useState } from 'react';
function ChatRoom({ messages }) {
const [message, setMessage] = useState('');
const handleChange = (event) => {
setMessage(event.target.value);
}
const handleSubmit = (event) => {
event.preventDefault();
fetch('/chat_rooms', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({ message: message })
});
setMessage('');
}
return (
<div className="Chat-room-container">
<div className="Chat-messages">
{messages.map((message, index) => (
<div key={index} className="Chat-message">
<p className="Chat-message-content">{message.content}</p>
<p className="Chat-message-user">{message.user}</p>
</div>
))}
</div>
<form className="Chat-form" onSubmit={handleSubmit}>
<input
type="text"
value={message}
onChange={handleChange}
placeholder="Type your message here"
/>
<button type="submit">Send</button>
</form>
</div>
);
}
export default ChatRoom;
This code defines the ChatRoom
component to render the list of messages and a form to send new messages.
Step 9: Start the servers
Start the Rails server:
rails s
And start the React client server:
cd client
npm start
Visit http://localhost:3000
in your browser to see the chat app in action!
Conclusion
In this tutorial, we walked through the process of setting up ActionCable in a Ruby on Rails API and creating a React front-end to send and receive real-time messages. We used create-react-app
to create a new React app and react-actioncable-provider
to handle the WebSocket connection and receive new messages.
By now, you should have a good understanding of how ActionCable works and how to use it to build real-time applications with Ruby on Rails and React.
To learn more about ActionCable, check out the official Rails documentation at https://guides.rubyonrails.org/action_cable_overview.html. For more information about React and create-react-app
, visit https://reactjs.org/ and https://create-react-app.dev/.
Thank you for reading!
Crafted by Wilbur Suero, a Software Engineer, who is passionate about building innovative and impactful solutions that drive business growth and operational excellence.