Skip to content

Commit

Permalink
Collection#fetch, Model#save, Model#fetch, and Model#destroy should a…
Browse files Browse the repository at this point in the history
…ll pass extra sync options to success callbacks.
  • Loading branch information
platinumazure committed Feb 11, 2015
1 parent 780c847 commit 1088d18
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 8 deletions.
18 changes: 10 additions & 8 deletions backbone.js
Expand Up @@ -538,7 +538,7 @@
// If the server returns an attributes hash that differs, the model's
// state will be `set` again.
save: function(key, val, options) {
var attrs, method, xhr, attributes = this.attributes;
var attrs, method, xhr, attributes = this.attributes, wait;

// Handle both `"key", value` and `{key: value}` -style arguments.
if (key == null || typeof key === 'object') {
Expand All @@ -549,18 +549,19 @@
}

options = _.extend({validate: true}, options);
wait = options.wait;

// If we're not waiting and attributes exist, save acts as
// `set(attr).save(null, opts)` with validation. Otherwise, check if
// the model will be valid when the attributes, if any, are set.
if (attrs && !options.wait) {
if (attrs && !wait) {
if (!this.set(attrs, options)) return false;
} else {
if (!this._validate(attrs, options)) return false;
}

// Set temporary attributes if `{wait: true}`.
if (attrs && options.wait) {
if (attrs && wait) {
this.attributes = _.extend({}, attributes, attrs);
}

Expand All @@ -573,7 +574,7 @@
// Ensure attributes are restored during synchronous saves.
model.attributes = attributes;
var serverAttrs = model.parse(resp, options);
if (options.wait) serverAttrs = _.extend(attrs || {}, serverAttrs);
if (wait) serverAttrs = _.extend(attrs || {}, serverAttrs);
if (_.isObject(serverAttrs) && !model.set(serverAttrs, options)) {
return false;
}
Expand All @@ -587,7 +588,7 @@
xhr = this.sync(method, this, options);

// Restore attributes.
if (attrs && options.wait) this.attributes = attributes;
if (attrs && wait) this.attributes = attributes;

return xhr;
},
Expand All @@ -599,14 +600,15 @@
options = options ? _.clone(options) : {};
var model = this;
var success = options.success;
var wait = options.wait;

var destroy = function() {
model.stopListening();
model.trigger('destroy', model, model.collection, options);
};

options.success = function(resp) {
if (options.wait || model.isNew()) destroy();
if (wait || model.isNew()) destroy();
if (success) success.call(options.context, model, resp, options);
if (!model.isNew()) model.trigger('sync', model, resp, options);
};
Expand All @@ -618,7 +620,7 @@
wrapError(this, options);

var xhr = this.sync('delete', this, options);
if (!options.wait) destroy();
if (!wait) destroy();
return xhr;
},

Expand Down Expand Up @@ -984,7 +986,7 @@
var collection = this;
var success = options.success;
options.success = function(model, resp, callbackOptions) {
if (options.wait) collection.add(model, callbackOptions);
if (wait) collection.add(model, callbackOptions);
if (success) success.call(callbackOptions.context, model, resp, callbackOptions);
};
model.save(null, options);
Expand Down
19 changes: 19 additions & 0 deletions test/collection.js
Expand Up @@ -1221,6 +1221,25 @@
Backbone.ajax = ajax;
});

test("fetch will pass extra options to success callback", 1, function () {
var SpecialSyncCollection = Backbone.Collection.extend({
url: '/test',
sync: function (method, collection, options) {
_.extend(options, { specialSync: true });
return Backbone.Collection.prototype.sync.call(this, method, collection, options);
}
});

var collection = new SpecialSyncCollection();

collection.fetch({ success: onSuccess });
this.ajaxSettings.success();

function onSuccess(collection, resp, options) {
ok(options.specialSync, "Options were passed correctly to callback");
}
});

test("`add` only `sort`s when necessary", 2, function () {
var collection = new (Backbone.Collection.extend({
comparator: 'a'
Expand Down
57 changes: 57 additions & 0 deletions test/model.js
Expand Up @@ -565,12 +565,50 @@
equal(this.ajaxSettings.url, '/collection/42');
});

test("save will pass extra options to success callback", 1, function () {
var SpecialSyncModel = Backbone.Model.extend({
sync: function (method, model, options) {
_.extend(options, { specialSync: true });
return Backbone.Model.prototype.sync.call(this, method, model, options);
},
urlRoot: '/test'
});

var model = new SpecialSyncModel();

model.save(null, { success: onSuccess });
this.ajaxSettings.success();

function onSuccess(model, response, options) {
ok(options.specialSync, "Options were passed correctly to callback");
}
});

test("fetch", 2, function() {
doc.fetch();
equal(this.syncArgs.method, 'read');
ok(_.isEqual(this.syncArgs.model, doc));
});

test("fetch will pass extra options to success callback", 1, function () {
var SpecialSyncModel = Backbone.Model.extend({
sync: function (method, model, options) {
_.extend(options, { specialSync: true });
return Backbone.Model.prototype.sync.call(this, method, model, options);
},
urlRoot: '/test'
});

var model = new SpecialSyncModel();

model.fetch({ success: onSuccess });
this.ajaxSettings.success();

function onSuccess(model, response, options) {
ok(options.specialSync, "Options were passed correctly to callback");
}
});

test("destroy", 3, function() {
doc.destroy();
equal(this.syncArgs.method, 'delete');
Expand All @@ -580,6 +618,25 @@
equal(newModel.destroy(), false);
});

test("destroy will pass extra options to success callback", 1, function () {
var SpecialSyncModel = Backbone.Model.extend({
sync: function (method, model, options) {
_.extend(options, { specialSync: true });
return Backbone.Model.prototype.sync.call(this, method, model, options);
},
urlRoot: '/test'
});

var model = new SpecialSyncModel({ id: 'id' });

model.destroy({ success: onSuccess });
this.ajaxSettings.success();

function onSuccess(model, response, options) {
ok(options.specialSync, "Options were passed correctly to callback");
}
});

test("non-persisted destroy", 1, function() {
var a = new Backbone.Model({ 'foo': 1, 'bar': 2, 'baz': 3});
a.sync = function() { throw "should not be called"; };
Expand Down

0 comments on commit 1088d18

Please sign in to comment.