Photo-1 Photo-2 Photo-3 Photo-4 Photo-5 Photo-6

@brentmc79

@brentmc79

Full-time web developer. Part-time smart ass.

I'm Brent Collier.

After a year and a half as an engineer on Twitter's Trust & Safety team, I'm looking for my next gig. Contact me if you know of something interesting.

#

Backbone.js + Rails 3.1 Asset Pipeline

Posted on 09/24/2011

I was working on a client app with a very js-heavy front end and I thought it would be a perfect opportunity to take a dive into Backbone.js. Unfortunately it didn't start off as smoothly as I had hoped and since Google was of minimal help while wrestling with these problems, I thought I'd document my troubles in hopes that I might help someone in a similar situation.

I started off following this tutorial by James Yu. I first downloaded backbone.js and included it in the app. Then I set up my directory structure under /app/assets/javascripts/backbone. Finally I copied the basic controller/model/views from the tutorial and tweaked them to work with an existing Rails controller in the app.

I then loaded the page in the browser and saw this in the js console:

Uncaught TypeError: Cannot call method 'extend' of undefined
    App.Views
    (anonymous function)
Uncaught TypeError: Cannot call method 'init' of undefined
    (anonymous function)
    jQuery.extend._Deferred.deferred.resolveWith
    jQuery.extend.ready
    DOMContentLoaded

I soon realized that I was missing underscore.js, a dependency of Backbone. So I downloaded it and added it to the app.

Reloading the page gave me another similar-yet-different error in the js console:

Uncaught TypeError: Cannot call method 'extend' of undefined
    (anonymous function)

It was referring to the following line in my backbone notes controller:

#app/assets/javascripts/backbone/controllers/notes.js
App.Controllers.Notes = Backbone.Controller.extend({

Backbone.Controller was undefined. WTF? This came directly from the sample code, so it should work. Right? I guess not.

A little Googling and browsing of the Backbone docs told me that I should change Backbone.Controller to Backbone.Router. Without digging through the Backbone repo history, I can only assume that this is due to an API change that hasn't been reflected in the tutorial. Once that was done, the error disappeared.

After that I spent some time fighting with the Rails Asset Pipeline and loading the Backbone files in the correct order. Unfortunately my attempt to reproduce and document those issues was unsuccessful. I think the problem was mostly due to me explicitly requiring the Backbone files, but in the wrong order. For some reason I just don't like using require_tree on the root js directory, but whatever, it seems to work fine in this case.

Here's what my js directory ultimately looked like:

|~app/
| |~assets/
| | |+images/
| | |~javascripts/
| | | |~backbone/
| | | | |~controllers/
| | | | | `-notes.js
| | | | |~models/
| | | | | `-note.js
| | | | |~views/
| | | | | `-index.js
| | | | `-application.js
| | | |-application.js
| | | |-backbone.js
| | | |-underscore.js

And here's my application.js:

//= require jquery
//= require underscore-min.js
//= require backbone.js
//= require_tree .

Pretty simple.

I started this blog post expecting to document my troubles with the Asset Pipeline, but in the end there didn't seem to be any. It was late, maybe I was tired. Who knows? What I do know is that when I was searching for info on using Backbone with the Asset Pipeline, I didn't find much.

Next I'm planning to expand my views and introduce some sort of templating library. Keep an eye out for another post around that...