2

This is basically what the original problem reduces to:

I have a Backbone model and I want to execute a certain action every time it saved successfully, but not after it's fetched. The cleanest and least intrusive way to do this, as I see it, would be to attach a handler to the sync event and check the XHR object: if it's a response to a GET, do one thing, and another if it was a POST.

However, looks like I cannot determine the HTTP method the jqXHR was created in response to... or can I?

Mihai
  • 2,835
  • 2
  • 28
  • 36
  • 1
    Why not override `save` and `fetch`? Or the `ajax` method on the model? – mu is too short Feb 03 '14 at 17:51
  • Because I want to execute the action on success, and this means waiting for the AJAX call to complete. Backbone triggers a `save` event immediately, and a `sync` event after the call is completed. – Mihai Feb 04 '14 at 17:52
  • 1
    But both `save` and `fetch` support `success` and `error` callbacks in their options and you can add those or wrap existing ones as needed. – mu is too short Feb 04 '14 at 18:29
  • Hmm, that could work too. Thanks! – Mihai Feb 04 '14 at 19:13

2 Answers2

2

You can override the Backbone.sync method like this :

var sync = Backbone.sync;

Backbone.sync = function(method, model, options) { // override the Backbone sync

                    // override the success callback if it exists
                    var success = options.success;
                    options.success = function(resp) {
                    if (success) success(model, resp, options);
                        // trigger the event that you want
                        model.trigger(methodMap[method]);
                    };

                    sync.call(this, method, model, options);
                };

methodMap looks like :

var methodMap = {
'create': 'POST',
'update': 'PUT',
'patch':  'PATCH',
'delete': 'DELETE',
'read':   'GET'
}

So in order to catch the GET/POST method all you have to do is :

initialize: function() { // your view initialize
    this.listenTo(this.model, "GET", /* your GET callback */);
    this.listenTo(this.model, "POST", /* your POST callback */);
}
Rida BENHAMMANE
  • 4,111
  • 1
  • 14
  • 25
0

You can override the save method to do whatever you want; something like this:

@MyApp.module "Entities", (Entities, App, Backbone, Marionette, $, _) ->

  class Entities.Model extends Backbone.Model

    save: (data, options = {}) ->
      ## do whatever you need to do ##
      super data, options

Then just extend your models from this definition instead of Backbone.Model, like so:

class Entities.MyModel extends App.Entities.Model
Tyler
  • 11,272
  • 9
  • 65
  • 105