How To Build A Real-time Commenting System with Rails

3 min readAug 23, 2017

Waving hand

Good News! We’ve launched an all new Chat Resource Center.

We recommend checking out our new Chat Resource Center, which includes overviews, tutorials, and design patterns for building and deploying mobile and web chat.

Take me to the Chat Resource Center →

This tutorial is a quick and easy example of Collaboration and Real-time Updates using PubNub to build an interactive real-time commenting system where a comment made in one user’s browser will appear in a second user’s the moment it’s submitted.

We’ll build a simple Rails application for a blog with multiple articles with individual comment streams. In a nutshell, we’ll be taking the basic comments system built in this tutorial, which only takes a couple minutes using Rails scaffolding. With that, I slightly adjusted the CSS to style it a bit as well.


Firstly, we add pubnub gem to Gemfile and then bundle install in terminal.

gem 'pubnub', '~> 4.0.21'


We added PubNub’s CDN to base the template on which every other template is rendered.

We have also added Turbolinks. As per their GitHub page:

Turbolinks makes navigating your web application faster. Get the performance benefits of a single-page application without the added complexity of a client-side JavaScript framework. Use HTML to render your views on the server side and link to pages as usual. When you follow a link, Turbolinks automatically fetches the page, swaps in its, and merges its, all without incurring the cost of a full page load.

We need to use Turbolinks because we want to use the functionality of a client-side framework without actually bringing it in, otherwise, it’d become more complex.

Flash block is only to show the success/error messages happening inside the application.

<!DOCTYPE html>
 <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>
 <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
 <script src=""></script>
 <%= csrf_meta_tags %>
  <div id="container">
     <%= link_to "Home", root_path %>
     <%= render 'layouts/user_widget' %>
     <% flash.each do |name, msg| %>
       <%= content_tag :div, msg, id: "flash_#{name}" %>
     <% end %>
     <%= yield %>


Here, we are instantiating PubNub on the server side to be used for server side operations, which we will see next. The keys between the client side and server side should be the same, so ideally, something like environment variables should be used, but for now we are hard coding it.

require 'pubnub'
$pubnub =
   subscribe_key: :demo,
   publish_key: :demo


This is where the magic is happening that when a new comment is created, whoever is watching that same article will get the new comment in real time. There are a couple of ways this could be done, but I am showing a simpler approach.

As soon as the comment is saved in a database, a message is published to the channel of that article. For this example purpose, I have created naming conventions for channel name as “comments-[article_id]”.

def create
  @commentable = Article.find(params[:article_id])
  @comment =
 	   channel: "comments-" + "#{}",
 	   message: { comment: comment_params["content"] }
    respond_to do |format|
     format.js { render :nothing => true }
    render :new


The first few parts of this file is just rendering HTML. Code in the script handles how to receive the message and how to render it. Firstly, we instantiated PubNub on client side with same keys as on server side. Then we subscribed to the particular channel to receive comments as per the naming conventions earlier mentioned. Then it listens for new messages and appends it to HTML.

<h1><%= %></h1>
<%= simple_format @article.content %>
    <%= link_to "Edit", edit_article_path(@article) %>
<%= render 'comments/comments' %>
    <%= render 'comments/form' %>
   var $pubnub = new PubNub({
       publishKey : 'demo',
       subscribeKey : 'demo'
   var article_id = "comments-" + window.location.pathname.split("/")[2];
       channels: [article_id]
       message: function(message) {
           $("#comments").append("<div class=\"comment\"><p>" + message.message["comment"] + "</p></div>")
   $("#new_comment").bind("ajax:complete", function(event,xhr,status){
    $('.actions input').keypress(function (e) {
        if (e.which == 13) {
            return false;

And that’s it! We now have a blog where comments are streamed in real time, no manual refreshing required.

More from PubNub

How to Create a Dating App: 7 Steps to Fit Any Design
Insights6 minMar 15, 2023

How to Create a Dating App: 7 Steps to Fit Any Design

There are common underlying technologies for a dating app, and in this post, we’ll talk about the major technologies and designs...

Michael Carroll

Michael Carroll

How to Create a Real-time Public Transportation Schedule App
Build6 minMar 14, 2023

How to Create a Real-time Public Transportation Schedule App

How to use geohashing, JavaScript, Google Maps API, and BART API to build a real-time public transit schedule app.

Michael Carroll

Michael Carroll

How to Create Real-Time Vehicle Location Tracking App
Build2 minMar 9, 2023

How to Create Real-Time Vehicle Location Tracking App

How to track and stream real-time vehicle location on a live-updating map using EON, JavaScript, and the Mapbox API.

Michael Carroll

Michael Carroll

Talk to an expert