We will create a simple Rails 6 chat application that utilizes web sockets to permit real-time communication. Action Cable meshes websockets with into Rails applications.To begin, we first create a new rails application.
rails new chatter
Once the application has been created, we generate a scaffold for our model. As this is a simple implementation of a chat application, our Chat model would only have one field, message
rails g scaffold Chat message:string
rails db:migrate
Once the scaffold is created, we then set the root path of our application
chatter/config/routes
root 'chats#index'
We then update the form for our chat to submit via javascript. Navigate to app/views/chats/_form.html.erb and update the form to
form_with(model: chat, remote: true)
This enables the form to be submitted via javascript. We will also update new.html.erb. We will add a div element that would hold newly created messages through action cable.
<% @chats.each do |chat| %>
<p><%= chat.message %></p>
<% end %>
<div id="new_message"%></div>
We will also update the controller to enable the create method to respond to javascript. In chats_controller,update as follows;
chats_controller, update as follows;
@chat = Chat.new(chat_params)
respond_to do |format|
if @chat.save
# format.html { redirect_to @chat, notice: 'Chat was successfully created.' }
# format.json { render :show, status: :created, location: @chat }
format.js
Also update the new method to contain the following
def new
@chats =Chat.all
@chat = Chat.new
end
Finally, we will also create a create.js.erb file to our views/chats/ folder.
Enter Action Cable
As previously stated, Action Cable enables real-time communication via web sockets. To get started, we first generate a channel that we will stream from. Create a new channel
rails g channel room
This would generate several files. We first look at room_channel.rb. We update the subscribed method to stream from room_channel
def subscribed
stream from "room_channel"
end
We then look at room_channel.js. Three functions are defined here. For this application, we are solely interested in the received function. Here, we state what operations should be carried out when channel receives data. We want the new message that was submitted to be displayed on the screen. So we create new elements and pass the message into it and render it out as HTML.
var node = document.createElement("P");
var textnode = document.createTextNode(data.content.message);
node.appendChild(textnode);
document.getElementById("new_message").appendChild(node);
document.getElementById('chat_message').value= ''
We look at the controller for chats again and update the create method. On the successful creation of a new chat message, we want to broadcast this chat message to our room_channel. We update the create method to reflect these changes:
def create
@chat = Chat.new(chat_params)
respond_to do |format|
if @chat.save
ActionCable.server.broadcast 'room_channel', content: @chat
format.html { redirect_to @chat, notice: 'Chat was successfully created.' }
format.json { render :show, status: :created, location: @chat }
format.js
else
format.html { render :new }
format.json { render json: @chat.errors, status: :unprocessable_entity }
end
end
end
We can finally test our application to see our chat work in real-time! Thatβs it!
README
This README would normally document whatever steps are necessary to get the application up and running.
Things you may want to cover:
-
Ruby version
-
System dependencies
-
Configuration
-
Database creation
-
Database initialization
-
How to run the test suite
-
Services (job queues, cache servers, search engines, etc.)
-
Deployment instructions
-
...
Top comments (4)
Whoops! I've updated the repo to include the create.js.erb file. Thank you
By the way, you also got a typo in the room_channel.rb:
Amazing! you also can add some magic to your chat with brand new ActionText from rails 6 core, I will be c&p an old post I have soon if you have any doubt :)
Hi, I really like how you explain it but, I can't find the create.js.erb file in that directory on github