Solution for those who like Action Cable but hate writing JavaScript
Paweł Dąbrowski
Posted on July 21, 2020
Introduction
Cable Ready is a great addition for Action Cable, especially if you don't like to write JavaScript code to interact with your website's DOM in a real-time. It helps us to quickly write real-time applications that work out of the box.
To demonstrate the features that the gem provides, we will build a simple chat where new messages will appear on the website without reloading. We will start with creating a brand-new Rails application, creating a little code, adding the Cable Ready gem, and making things real-time.
Demo
At the end of the article, we will have fully working simple chat:
Creating example application
Our application will consist of only one model: Message
. The model will have the following columns: username
and body
. The main purpose of the application is to let guests to simply write messages on the chat.
Application sekeleton
We will use Ruby 2.7.0
and Rails in version 6.0.3.2
. Since we don't need anything fancy on the database side, we will use SQLite
as a database engine.
rails new chat
cd chat
Model
As mentioned before, we would need one model - Message
where we will save the guest username along with the message that will appear in the chat. Let's create it:
rails g model Message username:string body:text
rails db:setup
rails db:migrate
Controller
We will need a controller to display messages and save new messages. Let's create one and save the following code into app/controllers/messages_controller.rb
:
class MessagesController < ApplicationController
def index
@message = Message.new
@messages = Message.order('created_at DESC')
end
def create
Message.create!(message_params)
redirect_to :messages
end
private
def message_params
params.require(:message).permit(:username, :body)
end
end
update routes in config/routes.rb
Rails.application.routes.draw do
resources :messages, only: %i[index create]
root to: 'messages#index'
end
and create app/views/messages/index.html.erb
view:
Current messages:
<ul>
<% @messages.each do |message| %>
<li><%= message.username %>: <%= message.body %>
<% end %>
</ul>
<h2>Add new message:</h2>
<%= form_for(@message) do |f| %>
<%= f.text_field :username, placeholder: 'username' %>
<%= f.text_area :body, placeholder: 'message' %>
<%= f.submit 'Send' %>
<% end %>
Now our "application" works but looks terrible and page is reloading each time we hit the Send
button.
Adding proper styles to the application
Before we add Cable Ready to our application, let's refactor the look a little bit so it looks more like a web chat.
Bootstrap installation
We will use the Bootstrap framework to save tons of time and adding nicely look to our simple application. The installation process is simple and consists of two steps. The first one is to install the library using yarn:
yarn add bootstrap@4.3.1
and the second one is to load styles. Update app/assets/stylesheets/application.css
and add the following line:
*= require bootstrap
Updating styles of messages list and new message form
Make sure that your app/views/layouts/application.html.erb
looks like the following:
<!DOCTYPE html>
<html>
<head>
<title>Chat</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<div class="flex-md-row p-3 px-md-4 mb-3 bg-white border-bottom box-shadow">
<h5 class="text-center">Simple chat</h5>
</div>
<div class="container">
<%= yield %>
</div>
</body>
</html>
and app/views/messages/index.html.erb
:
<div class="row justify-content-center">
<div class='col-6'>
<div class="list-group" id="messages">
<% @messages.each do |message| %>
<a href="#" class="list-group-item list-group-item-action">
<p class="mb-1"><%= message.body %></p>
<small class="text-muted"><%= message.username %></small>
</a>
<% end %>
</div>
</div>
</div>
<div class="row justify-content-center">
<div class='col-6'>
<hr class="mt-3 mb-3"/>
<h2>Add new message:</h2>
<%= form_for(@message) do |f| %>
<div class="form-group">
<label>Username</label>
<%= f.text_field :username, placeholder: 'username', class: 'form-control' %>
</div>
<div class="form-group">
<label>Message</label>
<%= f.text_area :body, placeholder: 'message', class: 'form-control' %>
</div>
<%= f.submit 'Send', class: 'btn btn-primary' %>
<% end %>
</div>
</div>
Now our application looks way better:
Making our chat real-time
It's time to update our code so new chat messages will appear without reloading the whole page. In the first step, we will update the form so the request will be sent in the background via AJAX, not as the normal POST request with redirection. In the second step, we will finally add ActionCable along with CableReady to make real-time updates.
Continue reading on https://pdabrowski.com/articles/cable-ready-with-action-cable
Posted on July 21, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.