1

I'm trying to send a model to a REST service using save(), but I need to pass a header parameter along with the json data so that the correct service is invoked (spring can use the headers to route the call to the right handler). That is, I'm not really saving the model, I'm performing an specific action upon it (in this case, it's an approval action). The PUT url should look something like this:

http://server/name/1

And this shouldn't change because the resource identity isn't changing. But, the headers should include a header containing the action. In this case we'll call the parameter 'command', and this specific example the value of command is 'approve'.

I've tried adding an object with a data field to the save:

model.save({data: {command:'approve'}})

But that simply adds the object associated with the data to the json data in the body of the request. I've read that this approach works on the fetch side to add the given data as params, but on save it seems to not work according to my expectations. I've single stepped through the backbone code and if the data option exists on a save it is merged with the model.

As I have no control over the service interface I have to work out how to to set the header parameter. Can anyone give me some guidance as to how to achieve this at the point of saving the model?

Software Engineer
  • 15,457
  • 7
  • 74
  • 102

2 Answers2

1

You could tackle this a couple of different ways.

You could override Backbone syncwith your own implementation, as described here. Within your sync implementation, you would pull out certain params (like approve), and jam them into the URL.

Or you could override the Model.url.

Community
  • 1
  • 1
Bart
  • 6,694
  • 6
  • 43
  • 53
  • Thanks Bart. Overriding backbone synch isn't a good solution to this difficult problem, because it would need to be fully rewritten to remove it's current undesirable behavior and then I'd have the problem of keeping my version up to date with changes in the framework. And, it turns out that query-strings are the wrong way to go after all (IMO), so overriding Model.url won't help either. – Software Engineer Dec 19 '13 at 23:05
0

After a few hours I finally came up with a working solution. I started with the save command:

model.save({command:'approve'})

And then I overrode backbone's ajax command:

    Backbone.ajax = function () {
    var args = Array.prototype.slice.call(arguments, 0);

    if (args[0].data) {
        var model = JSON.parse(args[0].data);
        var command = model.command;
        if (command) {
            args[0]['headers'] = { command: command};
        }
    }

    return Backbone.$.ajax.apply(Backbone.$, args);
}

This code looks for the command value on the model (Backbone.save put it there), and pushes it to the headers. The next step will be to simply remove the command from the model before returning it.

Software Engineer
  • 15,457
  • 7
  • 74
  • 102