Backbone.js Tutorial: Backbone.sync
by
at 2012-12-20 08:00:00
original http://feedproxy.google.com/~r/dailyjs/~3/sir13oqvmI4/backbone-tutorial-4
- Part 1: Build Environment
- Part 2: Google's APIs and RequireJS
- Part 3: Authenticating with OAuth2
- Part 4: Backbone.sync
- Part 5: List Views
Preparation
Before starting this tutorial, you’ll need the following:
- alexyoung / dailyjs-backbone-tutorial at commit
c1d5a2e7cc
- The API key from part 2
- The “Client ID” key from part 2
- Update
app/js/config.js
with your keys (if you’ve checked out my source)
To check out the source, run the following commands (or use a suitable Git GUI tool):
git clone git@github.com:alexyoung/dailyjs-backbone-tutorial.git
cd dailyjs-backbone-tutorial
git reset --hard c1d5a2e7cc
Google’s Tasks API
To recap: the point of this tutorial series is to build a Backbone.js single page application that uses client-side JavaScript to communicate with Google’s authentication and to-do list APIs. Got that? Good!
Google provides access to our to-do lists through two APIs:
When loading Google’s JavaScript, the browser is bestowed with a global called gapi
that provides access to various objects and methods. In the last part, I quietly included a call to gapi.client.load
that loads the tasks
API:
gapi.client.load('tasks', 'v1', function() { /* Loaded */ });
This can be found in app/js/gapi.js
. The remaining challenge before building the interface is to implement a new Backbone.sync
method that uses gapi
to communicate with the Tasks and Tasklists APIs.
Backbone.sync Structure
I’ve already talked about the overall structure of Backbone.sync
in part 2. The pattern I’ll use in these tutorials is fairly generic, so you could use the same approach to communicate with something other than Google’s APIs.
The sync
method itself takes three arguments, the first of which is the method
(create
, update
, delete
, and read
). We need to map method
to something Google’s API can understand.
This is what we’ve got so far:
Backbone.sync = function(method, model, options) {
options || (options = {});
switch (method) {
case 'create':
break;
case 'update':
break;
case 'delete':
break;
case 'read':
break;
}
};
Google’s Tasks API methods map to the Backbone method
argument like this:
Google Tasks API | Backbone.sync Method | Description |
---|---|---|
insert | create | Create a new task. |
update | update | Update an existing task. |
delete | delete | Delete a task. |
list | read | Get a list of tasks. |
Even though Google’s API doesn’t look like the Rails 3-based RESTful API that Backbone.js is designed for out of the box, it’s still very close.
Making Requests with gapi
The gapi
object makes requests using this pattern:
- Call one of the
gapi.client.tasks
methods with the request content to get arequest
object - Call
request.execute
with a callback to send the request - The callback receives a
response
object, much like a standard Ajax request
Here’s what this looks like in reality:
var requestContent = {}
, request
, gapiResource;
gapiResource = 'tasks';
requestContent['tasklist'] = tasklistId; // Assuming we have one
requestContent['resource'] = model.toJSON();
// 'insert' is for creating new tasks
request = gapi.client.tasks[gapiResource].insert(requestContent);
// Send the request to the API
request.execute(function(res) {
// Handle the response
});
Looking at this, it’s clear that we need two models: Task
and TaskList
. There also need to be two corresponding collections: Tasks
and TaskLists
.
Backbone models and collections have URLs – these are used for making API requests. Similarly, Google’s APIs have URLs: tasks
and tasklists
, so by using the model URL Backbone.sync
can determine which API resource is required for a given request.
Models
Create a new directory called app/js/models
and add task.js
:
define(function() {
var Task = Backbone.Model.extend({
url: 'tasks'
});
return Task;
});
You’ll also want to create a app/js/models/tasklist.js
:
define(function() {
var TaskList = Backbone.Model.extend({
url: 'tasklists'
});
return TaskList;
});
Collections
Create another new directory called app/js/collections
and add tasklists.js
:
define(['models/tasklist'], function(TaskList) {
var TaskLists = Backbone.Collection.extend({
model: TaskList
, url: 'tasklists'
});
return TaskLists;
});
We’re going to use the TaskList
collection later on to load your task lists.
Making API Requests
Open up app/js/gapi.js
and add a new line after line 36:
app.views.auth.$el.hide();
$('#signed-in-container').show();
self.trigger('ready'); // This one
This 'ready'
event will be used to signify that authentication was successful, and the Tasks API is ready for use. Next, add the following two lines to Backbone.sync
, inside the read
switch case:
case 'read':
var request = gapi.client.tasks[model.url].list(options.data);
Backbone.gapiRequest(request, method, model, options);
break;
This code creates a request, and then Backbone.gapiRequest
will execute it and delegate the response.
Here’s the most basic Backbone.gapiRequest
implementation:
Backbone.gapiRequest = function(request, method, model, options) {
var result;
request.execute(function(res) {
if (res.error) {
if (options.error) options.error(res);
} else if (options.success) {
result = res.items;
options.success(result, true, request);
}
});
};
All it does is run request.execute
, which is provided by Google, and then maps the result to be compatible with Backbone’s API by running the success
and error
callbacks.
Just so you can see something is really happening, open app/js/app.js
and make it load the TaskLists
collection by changing the define
invocation at the top:
define([
'gapi'
, 'views/app'
, 'views/auth'
, 'collections/tasklists'
],
function(ApiManager, AppView, AuthView, TaskLists) {
Now add this to the connectGapi
method:
this.apiManager.on('ready', function() {
self.collections.lists.fetch({ data: { userId: '@me' }, success: function(res) {
_.each(res.models, function(model) {
console.log(model.get('title'));
});
}});
});
That code uses Underscore’s each
method to iterate over each “model” returned by Backbone.sync
, which is called by the TaskList
collection.
Run the server with npm start
, and visit http://localhost:8080
. If you run it in a browser that supports console
, then you should see your task lists printed out.
If you’ve got this working then you’re not far off building a real world Backbone.js app that communicates with Google’s APIs. The same concepts can be applied to other Google JavaScript APIs.
Summary
The full source for this tutorial can be found in alexyoung / dailyjs-backbone-tutorial, commit fcd653ec6.