Real-time Chat Blog

How To Build A Real-time Commenting System with Rails

3 min read Anmol Agrawal on Aug 23, 2017
Try PubNub Today

Free up to 1MM monthly messages. No credit card required.

Subscribe to our newsletter

By submitting this form, you are agreeing to our Terms and Conditions and Privacy Policy.

How to use Rails and PubNub to build a real-time commenting system that streams comments with no refreshing required.

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

NPP and HIPAA: Notice of Privacy Practices Definition
Healthcare CategoryJan 6, 20235 min read

NPP and HIPAA: Notice of Privacy Practices Definition

A Notice of Privacy Practices (NPP) is one of the requirements of HIPAA and helps patients understand their personal data rights.

Michael Carroll

Michael Carroll

HIPAA Violation Examples
Healthcare CategoryJan 5, 20236 min read

HIPAA Violation Examples

HIPAA violations can be financially expensive and devastating to a brand. Examine some examples of HIPAA violations, and learn...

Michael Carroll

Michael Carroll

HIPAA Technical Safeguards: How To Protect Sensitive Data
Healthcare CategoryJan 5, 20236 min read

HIPAA Technical Safeguards: How To Protect Sensitive Data

HIPAA covered entities must follow the five technical safeguards to achieve HIPAA compliance and prevent data corruption.

Michael Carroll

Michael Carroll