3

The API I am hitting explodes if I send any "extra" properties back to the server. Now, I'm sure I've broken some MVC rules or something by having properties on my client side Backbone model that don't exist server side, but, what I need to do is initiate a CREATE request but only pass through some of the attributes from my model I am initiating the CREATE request from.

I can easily do this in backbone:

Model.save({key: val}, {patch: true}); 

And then modify the Backbone sync methodMap defaults patch routes to POST instead of PATCH and that nets me exactly what I'm looking for except that later on I want to actually be able to PATCH (instead of POST) when appropriate. I just need it to POST as if it were PATCHing for create actions only (not for update actions!).

So, in short, I need to take something like this:

new Backbone.Model({'foo': 'bar', 'baz': 'beh'});

And tell it to sync itself to the server, but ONLY send 'foo' across and not send 'baz', but it has to send it as a POST (it can't be a PATCH).

Any ideas?

cmcculloh
  • 47,596
  • 40
  • 105
  • 130

3 Answers3

10

Below is a save override that can be placed in a base Backbone model or any individual model as appropriate. It may not cover every use case but it seems to fit this one.

JS Fiddle: http://jsfiddle.net/hEN88/1/

This override allows you to set a 'serverAttrs' array on any model to filter which properties are sent to the server.

save: function (attrs, options) { 
    attrs = attrs || this.toJSON();
    options = options || {};

    // If model defines serverAttrs, replace attrs with trimmed version
    if (this.serverAttrs) attrs = _.pick(attrs, this.serverAttrs);

    // Move attrs to options
    options.attrs = attrs;

    // Call super with attrs moved to options
    Backbone.Model.prototype.save.call(this, attrs, options);
}
Adam Alexander
  • 15,132
  • 5
  • 42
  • 41
  • 1
    One minor edit. Instead of passing an empty object through to the save.call(), put the attrs there and this will work for create and patch. So: `Backbone.Model.prototype.save.call(this, attrs, options);` – cmcculloh Apr 10 '13 at 15:20
  • Nice find! Updated answer and JS Fiddle link. – Adam Alexander Apr 10 '13 at 20:17
  • fyi: if doing this in coffeescript via extends with ROR asset pipeline, and your class name is alphabetically before whatever it is you're extending, you need to explicitly require it via `##= require ./base`. HTH – hoffmanc Jul 06 '13 at 21:27
  • This is great. I'm thinking it could be better to define excludeAttrs rather than serverAttrs as in _most_ cases it would be shorter to define the varibles you **don't** want sent rather than all the ones you do want sent. You would just use _.omit(attr, this.excludeAttrs). – Will Jul 30 '13 at 23:59
1

This question sounds like it may be a dupe of Exclude model properties when syncing (Backbone.js) and Backbone.js/express.js parameters for model.save()

The answer in both of those cases came down to overriding the save() function.

Community
  • 1
  • 1
David Brainer
  • 6,223
  • 3
  • 18
  • 16
0

You can override toJSON method

// set viewOnlyAttrs for attributes no need to save
viewOnlyAttrs: ['url'],

toJSON: function(options) {
  var obj = this;

  // if is calling from model's save method
  if(_.has(options || {}, 'emulateHTTP') && obj.viewOnlyAttrs)
    return _.omit(obj.attributes, obj.viewOnlyAttrs);

  return Backbone.Model.prototype.toJSON.call(this, options);
}
John Xiao
  • 1,680
  • 2
  • 18
  • 24