A0fkgvnqul556xxypfrf

Quick Wins with Backbone.js

Philip Woo

On one of our projects, we had an opportunity to refactor our existing code to use Backbone.js. We felt that Backbone was a good choice since we were dealing with improving some javascript components in our app and not looking to rewrite our entire app itself, which other JS frameworks (ala Angular.js, Ember.js) would have been better suited to do. Here are examples of some quick wins we managed to gain by taking advantage of the nice tools that Backbone.js gave us.

Backbone.js likes to REST

Our code had various CoffeeScript classes, most of which had similar looking functions like these:

class Scenario
  save: ->
    $.ajax 'some/url'
      type: 'POST'
      dataType: 'json'
      data: { step: {foo: 'bar', ping: 'pong'} }
      success: (data, status, jqXHR) ->
        ...
      error: (jqXHR, textStatus, errorThrown) ->
        ...
  findAll: (scenarioId)->
    $.ajax 'some/url'
      type: 'POST'
      dataType: 'json'
      data: { step: {foo: 'bar', ping: 'pong'} }
      success: (data, status, jqXHR) ->
        ...
      error: (jqXHR, textStatus, errorThrown) ->
        ...

Sure, there's nothing too complicated about a jquery.ajax function, but it does get repetitive and tedious writing these out on all our classes. Luckily, Backbone.js knows how to handle REST APIs right out of the box, which is especially nice if you happen to be using it on top of Rails (like we are) and use various `resources :model_name` to define your routes. With that in mind, we can get rid of all the ajax functions that we were defining, and whenever we need to save one of our objects, we have various options to do so. A Backbone Collection is an object that, like its name suggests, holds a collection of individual model objects. In our app, we have a Backbone `Step` model and a `Steps` collection to hold all our individual steps as they get created. So to create a new `Step`:

  steps = new Steps
  stepAttributes = {foo: 'bar', ping: 'pong'}

  # this makes a POST request with stepAttributes to save it to our database
  # as well as add a Step object to the steps collection
  steps.create stepAttributes
    success: (model, response, options) ->
      ...
    error: ->
      ...

Or if we have a model that doesn't have a collection defined, it wouldn't look much different:

  scenario = new Scenario({name: 'Backbone'})
  scenario.save
    success: (model, response, options) ->
       ...
    error: ->
      ...

Either way, it saves us the trouble of having to define a bunch of ajax functions that map to our API, which meant we got to delete a lot of code. Hurray.

"Hey, I heard that"

Backbone has a respectable list of events (you can trigger your own if you want too) that get broadcasted when you do certain things. Our old code had a `GuiController` class that had varios functions defined to listen to button clicks and other user behavior and displaying and/or hiding corresponding elements. With Backbone, we instead listen to a model being saved or a model object getting added to a collection in a Backbone View object:

class Steps extends Backbone.View
  initialize: ->
    # when something gets added to this view's collection, call render function
    this.listenTo(this.collection, "add", this.render) 

  render: (model, collection, option) ->
    # model parameter in this case is the model that got added to the collection,
    # ie. responsible for triggering the add event
    $("some-element").append(model.attr("name"))

 

Of course the above examples are some of the very simple aspects of Backbone and are really just scratching the surface of what all the neat things it gives you. If you find that your Rails app's javascript folders/files are growing and could use an extra layer of organization, leveraging the freebies that come with a javascript library/framework could be an option worth exploring (especially with the myriad options that are at your disposal).