In Part 1 of the CloudEdit Backbone.js Tutorial, we developed a basic Rails application using Backbone.js that lets users create and edit documents in the cloud. Now, in Part 2, we’ll do some refactoring to clean up parts of the app and make things more readable and maintainable.
Specifically, we’ll be doing the following:
- Use Backbone Collections.
- Use Underscore templating.
- Use event binding to refresh views.
This update won’t change anything in the UI: it’s simply some housekeeping to tidy up the code.
As you may remember in Part 1, we loaded the list of documents for the
documents#index action via a call to
$.getJSON, and then instantiated all the documents in an array. But, we can provide a better abstraction by defining a Backbone Collection as follows:
It’s pretty simple: we tell the collection that it should hold the
Document model (via the model attribute), and that the resource to fetch the documents from the server is located at
/documents. Also notice that I’m organizing collections in the same way as the MVC components: the definition is located under the
Now, we can update the
documents#index action in the Backbone controller as follows:
All we did was instantiate a new instance of the
Documents collection, and then call fetch with a success callback that passes the collection to the
App.Views.Index view. We didn’t even need to change any Rails code: the original RESTful
/documents action is identical.
Previously, we built up our views using string concatenation. I did this so that we could focus on Backbone.js itself, and not any particular templating language.
However, for anything more than trivial views, string concatenation is a maintenance nightmare. Luckily, http://documentcloud.github.com/jammit/ provides an easy integration with http://documentcloud.github.com/underscore/ templates, which are powerful and very similar to ERb.
.jst files. It will package up the templates into a global
JST object that you can use to render your templates into strings. To make Jammit aware of these files, I simply added an entry for
app/views/**/*.jst in my
app package in
Convert the Views
Next, we need to convert our views to Underscore templates. This is the fun part, since we get to see the ugly jumble of strings turn into beautiful templates.
Let’s first convert the strings in the
App.Views.Edit view into the
document.jst template. This would turn the following code:
If you’re familiar with ERb templates, this is pretty straightforward. Basically, the template now uses the
model object that is passed in to fill in all the data. The call to render this template is:
No more complicated string concatenation!
Now let’s convert the strings in
App.Views.Index into the
documents_collection.jst template. This turns:
Similar to the
document.jst template, this template derives all its data from the
collection object that is passed in. We would render it like:
If you take a look at the
App.Views.Index models, they are now significantly simpler after moving the HTML out.
Model Event Binding
One last minor cleanup that we’ll do is to avoid calling
render in the
save method of
App.Views.Edit. Instead, we’ll bind the
render call to any model changes, like so:
Now, whenever the
document model changes, the view will be re-rendered. This ensures that the view will always stay up-to-date with the model, no matter what piece of code happens to change it. This is actually fundamental to the philosophy of Backbone, which is to separate the model data from the controllers and views.
Let’s take a look at the updated directory structure after these changes:
We added two items: the .jst files, and the Backbone collections folder. Overall, the structure is still nicely organized, and its easy to see at a glance how everything connects.