Latest Update
Building Chatter: Part 7 – hooking up realtime, and Handlebars.js
So, after part 6 we have demonstrated that we can implement real time updates to users, without needing them to refresh their web page. We’re going to need to implement some controls on this, so that we aren’t firing updates out into the ether without anyone there to listen for them, but we will do that in a minute.
First, we’re going to need to use that message the browser receives to update the web page, rather than just firing an alert message with the details. There are a number of ways of doing this, but probably the best is to start using a specialist front end technology.
Handlebars.js gives us a templating system that we can use to simply update web pages by parsing JSON and updating HTML templates with the values. We can use the power of Rails’ asset packaging system to declare these templates in advance, in a ready-to-use precompiled format. This also means that when in production, our users will simply be downloading 1 JS file (“application.js”) which will have all of the functionality that they could need in it, which is ideal.
To make this application into a full client-side app, then we would ideally use a JS MVC framework such as Backbone.js or Spine.js, or even something more full-featured such as ExtJS or SproutCore. However that is a little beyond the scope of this tutorial, but we may revisit this later on.
Making it look nicer
So far it all looks really rather boring, so we’ll use a CSS framework to make things a little more interesting. Twitter have just released Bootstrap, an open source framework which is fantastic and simple to use, so we’ll use that code to improve the look of our application. If we incorporate this now, before we start writing the templates, we won’t have to re-do the job later on.
In application.css change the require lines to read as follows:
|
1 2 3 |
<code>*= require_self<
*= require bootstrap
*= require users</code> |
We have changed the require tree line to “require user” because we don’t want to include all of the scaffolding CSS that Rails generates for us. Create a new file “app/assets/stylesheets/users.css.scss” – and if you want to override any styles, put them in there. Then create a file called “app/assets/stylesheets/bootstrap.css” and copy the contents of this file into it.
We now need to copy the JS (needed to give us some great features with the framework) and then we can start building our templates. Copy all of the JS filesĀ from here into “app/assets/bootstrapjs” and then add the following two lines to “app/assets/javascripts/application.js” above the line saying “//= require_tree . “:
|
1 2 |
<code>//= require ../bootstrapjs/bootstrap-twipsy
//= require_tree ../bootstrapjs</code> |
Finally, we need to update our application’s layout to use the features that Bootstrap gives us. This is going to be a major change of the file “app/views/layouts/application.html.erb”, so I have provided the code for you in this gist file here – simply copy and paste it into your application.html.erb file. Some of our formatting will have been broken with this, but we can deal with that later. Now we are going to edit “app/views/dashboard/index.html.erb” to reflect the change of layout:
|
1 2 3 4 |
<code><h3>Latest Posts</h3>
<div id="timeline">
<%= render @posts %>
</div></code> |
Finally, update “app/views/posts/_post.html.erb” to be:
|
1 2 3 4 5 6 7 8 9 10 11 |
<code><blockquote>
<p><%= post.body %></p>
<small>
<% if post.user == current_user %>
You
<% else %>
<%= link_to post.user.username, "#" %>
<% end %>.
<%= time_ago_in_words(post.created_at) %> ago.
</small>
</blockquote></code> |
If we fire up the server now, we should see something like the following:

Which looks rather more professional, don’t you think? OK, lets start implementing Handlebars, so we can hook up the realtime functionality.
Handlebars and Mustaches
Handlebars is an extension of the Mustache templating language, which is hugely powerful, and very easy to use. If you have ever used the Liquid Templating Language in ruby, then the basic syntax is a little similar – you print out variables by enclosing them in curly-brackets – {{ variable }}.
To make our life easier, we are going to install a new gem “handlebars_assets”. We need to add this to our Gemfile, in the “group :assets do” section:
|
1 |
<code>gem 'handlebars_assets'</code> |
Now run “bundle” to add the gem, and we can start building our templates. We need to tell the asset packager where the template files are located, and that we will be using handlebars. Add the following lines to “app/assets/javascript/application.js”, above the line that says “//= require_tree .”:
|
1 2 3 |
<code>//= require handlebars.vm
//= require_tree ../templates
</code> |
Now we are ready to start building the templates. To do this, we will create a new folder in “app/assets” called “templates”, and then create our template files in there. Convention is that Handlebars files have a “.hbs” suffix, and because we want to compile them for speed, we also add “.jst”, so files are “filename.jst.hbs”. The location for each of the following files is in the comment at the top, so create the following:
|
1 2 3 4 5 6 7 |
<code># app/assets/templates/post.jst.hbs
<blockquote>
<p>{{body}}</p>
<small>
<a href="#">{{user.username}}</a>
</small>
</blockquote></code> |
Before we create any more, we’ll put this in action and show how it works. Open up “app/views/layouts/application.html.erb” again, and change this method:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
<code><script>
// -------------------
// LISTEN FOR MESSAGES
// -------------------
PUBNUB.subscribe({
channel : "<%= Digest::SHA1.hexdigest(current_user.username, current_user.created_at) %>",
callback : function(message) { alert(message) }
})
</script>
</code> |
To this:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<code><script>
function updateTimeline(message) {
var html = JST['post'](jQuery.parseJSON(message));
$('#timeline').prepend(html);
}
// -------------------
// LISTEN FOR MESSAGES
// -------------------
PUBNUB.subscribe({
channel : "<%= Digest::SHA1.hexdigest(current_user.username, current_user.created_at) %>",
callback : function(message) { updateTimeline(message) }
})
</script>
</code> |
Ok, let’s restart the server, and open up a console window – and like last time use the console to create a new post and see if it updates our web browser. So, with your browser open and displaying the app home page, type the following into a rails console (keep the app in sight) and see if it updates:
|
1 |
<code>Post.create(:body => "@USERNAME hello there")</code> |
You should see that you’ve got the new post appearing at the top of your list. Perfect. In the next installment, we will improve the UI of the app a little more, and speed up the interface by incorporating more Handlebars to make things faster, as well as start building an API!
If you need the source code from this episode, check my Github – http://github.com/jgwmaxwell, this episode is in branch “part7”.
Recent Comments