146

I'm trying out Backbone.js, and one of the things I'm trying is to make a call to a remote API, so I need to be able to override Backbone.sync, as I understand the documentation.

There isn't an example of how to do that in the documentation itself, and there doesn't appear to be a google group for Backbone... can someone point out an example for doing this?

Scott Foubister
  • 135
  • 1
  • 7
picardo
  • 24,530
  • 33
  • 104
  • 151
  • 4
    In the absence of a Google Group, try checking out the #documentcloud room on freenode and asking your question there. Just be sure to come back here and answer your own question if you get an answer. There's a lot of great discussions there and it's nice to codify it and make it searchable for those that come after you. – Andrew De Andrade Feb 23 '11 at 22:06
  • 3
    FYI: http://groups.google.com/group/backbonejs – Drew Dara-Abrams Sep 21 '11 at 08:11

3 Answers3

224

Take a look at this annotated source example where they overwrite Backbone.sync with a localstorage alternative

backbone-localStorage

Basically Backbone.sync should be a function that takes 4 arguments:

Backbone.sync = function(method, model, options) { };

You need to fire either options.success or options.error depending on whether the method succeeded. The methods are in the format:

  • "create" : expected that you create the model on the server
  • "read" : expected that you read this model from the server and return it
  • "update" : expected that you update the model on the server with the argument
  • "delete" : expected that you delete the model from the server.

You need to implement those 4 methods and define whatever you want for your "server"

Of course these are only the things that Backbone.sync must implement. You may implement more methods and you may pass more paramaters back to success but it's best not to do this.

It's best to make sure it does the same as Backbone.sync does currently so that your programming to an interface rather then an implementation. If you want to switch out your modified Backbone.sync for say the localStorage one you won't have to extend it yourself to match your extended Backbone.sync"

[Edit]

Also do note that you can use multiple implementations of sync. Every reference to Backbone.sync is actaully (this.sync || Backbone.sync) so you just have to do something like:

var MyModel = Backbone.Model.extend({ 
    ...

    "sync": myOwnSpecificSync,

    ...
});

Backbone.sync is just the default global one that all models use unless the models have a sync method specifically set.

Yura
  • 2,690
  • 26
  • 32
Raynos
  • 166,823
  • 56
  • 351
  • 396
  • 2
    What if I want a model to fetch from localStorage, while another one fetches from the server? Is that possible yet? – picardo Feb 23 '11 at 20:43
  • 19
    `(this.sync || Backbone.sync)` See edit. A further tip is to read the annotated source of backbone. It's all there! – Raynos Feb 23 '11 at 20:46
  • 3
    The detail after \[Edit] about each model having it's own sync is super important! Thanks! – Abel Apr 21 '11 at 05:34
  • 26
    +1 for mentioning the fact that you can override a specific model's sync method. – Chetan Apr 24 '11 at 20:48
  • Does this mean that doing `"sync": new window.Store("myOwnLocallyStoredModel")` is possible, using the `localStorage` adaptor? – Industrial Jan 02 '12 at 13:11
  • if i were to override backbone.sync as stated above you can have multiple implementation via model. But what i dont get is where to put the codes to override sync and how would you call it? – n0minal Mar 30 '12 at 01:56
  • 12
    Just one addition: if you want to call the "default" `sync` from anywhere in your code (typically an overrydden `sync`), just do a `Backbone.sync.call(this, method, this, options)`. – asymmetric Apr 27 '12 at 19:50
  • I know this topic is old, but seems like many people still find this to be the best answer around (and probably it is), so it should be noted that the latest version of Backbone.localStorage can be found [here](https://github.com/jeromegn/Backbone.localStorage/blob/master/backbone.localStorage.js). – GavinoGrifoni Feb 12 '15 at 12:32
15

I know this answer is a bit too late, and the answer from @Raynos is great, but I did it a bit differently, and maybe it would be useful for you or for any other person trying to use an API with Backbone.

Instead of overriding Backbone.sync, I overrided Backbone.ajax, because it's where the ajax request is made.

Here's an example :

// Set the default implementation of `Backbone.ajax` to proxy through to `$`.
Backbone.ajax = function() {
    var args = Array.prototype.slice.call(arguments, 0);

    // Here, I add the OAuth token (or any other token)
    // But before, I check that data exists, if not I add it
    if (args[0]['data'] === undefined) {
        args[0]['data'] = {};
    }
    args[0]['data']['token'] = 'any_api_token_here';

    return Backbone.$.ajax.apply(Backbone.$, args);
};
Benry
  • 5,298
  • 1
  • 24
  • 25
Cyril N.
  • 38,875
  • 36
  • 142
  • 243
11

I typically need to override backbone's sync method when I need to only sync certain attributes. A typical implementation looks like this:

sync: function (method, model, options) {
  options.data = _.pick(this.attributes, 'foo', 'bar', 'baz');
  return Backbone.sync.call(this, method, model, options);
}
Patrick McElhaney
  • 57,901
  • 40
  • 134
  • 167
Jesse Atkinson
  • 10,586
  • 13
  • 42
  • 45
  • and that goes into Model or Collection. – Gabe Rainbow Sep 19 '13 at 00:01
  • 3
    Minor suggestion: what about changing that last line to `Backbone.sync.apply(this, arguments);`? It's slightly more flexible if you, for example, decide to leave out the "options" argument in the overridden version of `sync`. – Lochlan Sep 17 '15 at 22:40
  • Something else for future finders of this question: _make sure to return Backbone.sync_ a la http://backbonejs.org/docs/backbone.html#section-62 – Lochlan Sep 18 '15 at 00:59
  • 1
    You can use `Backbone.model.save(attributes, {patch: true})` to do partial updates now – roborourke Sep 22 '16 at 16:51