Skip to content

Commit

Permalink
Much asked-for change. Instead of throwing an early error when adding…
Browse files Browse the repository at this point in the history
… duplicate models, Backbone will simply skip them instead.
  • Loading branch information
jashkenas committed Feb 13, 2012
1 parent b1e2e69 commit 18fba57
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 18 deletions.
14 changes: 11 additions & 3 deletions backbone.js
Expand Up @@ -501,7 +501,7 @@
// Add a model, or list of models to the set. Pass **silent** to avoid // Add a model, or list of models to the set. Pass **silent** to avoid
// firing the `add` event for every new model. // firing the `add` event for every new model.
add: function(models, options) { add: function(models, options) {
var i, index, length, model, cid, id, cids = {}, ids = {}; var i, index, length, model, cid, id, cids = {}, ids = {}, dups = [];
options || (options = {}); options || (options = {});
models = _.isArray(models) ? models.slice() : [models]; models = _.isArray(models) ? models.slice() : [models];


Expand All @@ -513,14 +513,21 @@
} }
if (cids[cid = model.cid] || this._byCid[cid] || if (cids[cid = model.cid] || this._byCid[cid] ||
(((id = model.id) != null) && (ids[id] || this._byId[id]))) { (((id = model.id) != null) && (ids[id] || this._byId[id]))) {
throw new Error("Can't add the same model to a collection twice"); dups.push(i);
continue;
} }
cids[cid] = ids[id] = model; cids[cid] = ids[id] = model;
} }


// Remove duplicates.
i = dups.length;
while (i--) {
models.splice(dups[i], 1);
}

// Listen to added models' events, and index models for lookup by // Listen to added models' events, and index models for lookup by
// `id` and by `cid`. // `id` and by `cid`.
for (i = 0; i < length; i++) { for (i = 0, length = models.length; i < length; i++) {
(model = models[i]).on('all', this._onModelEvent, this); (model = models[i]).on('all', this._onModelEvent, this);
this._byCid[model.cid] = model; this._byCid[model.cid] = model;
if (model.id != null) this._byId[model.id] = model; if (model.id != null) this._byId[model.id] = model;
Expand Down Expand Up @@ -705,6 +712,7 @@


// Prepare a model or hash of attributes to be added to this collection. // Prepare a model or hash of attributes to be added to this collection.
_prepareModel: function(model, options) { _prepareModel: function(model, options) {
options || (options = {});
if (!(model instanceof Backbone.Model)) { if (!(model instanceof Backbone.Model)) {
var attrs = model; var attrs = model;
options.collection = this; options.collection = this;
Expand Down
26 changes: 11 additions & 15 deletions test/collection.js
Expand Up @@ -124,22 +124,15 @@ $(document).ready(function() {
}); });


test("Collection: can't add model to collection twice", function() { test("Collection: can't add model to collection twice", function() {
raises(function(){ var col = new Backbone.Collection([{id: 1}, {id: 2}, {id: 1}, {id: 2}, {id: 3}]);
// no id, same cid equal(col.pluck('id').join(' '), '1 2 3');
var a2 = new Backbone.Model({label: a.label});
a2.cid = a.cid;
col.push(a2);
ok(false, "duplicate; expected add to fail");
}, "Can't add the same model to a collection twice");
}); });


test("Collection: can't add different model with same id to collection twice", function() { test("Collection: can't add different model with same id to collection twice", function() {
raises(function(){ var col = new Backbone.Collection;
var col = new Backbone.Collection; col.unshift({id: 101});
col.unshift({id: 101}); col.add({id: 101});
col.add({id: 101}); equal(col.length, 1);
ok(false, "duplicate; expected add to fail");
}, "Can't add the same model to a collection twice");
}); });


test("Collection: add model to multiple collections", function() { test("Collection: add model to multiple collections", function() {
Expand Down Expand Up @@ -518,8 +511,11 @@ $(document).ready(function() {
test("Collection: multiple copies of the same model", function() { test("Collection: multiple copies of the same model", function() {
var col = new Backbone.Collection(); var col = new Backbone.Collection();
var model = new Backbone.Model(); var model = new Backbone.Model();
raises(function() { col.add([model, model]); }); col.add([model, model]);
raises(function() { col.add([{id: 1}, {id: 1}]); }); equal(col.length, 1);
col.add([{id: 1}, {id: 1}]);
equal(col.length, 2);
equal(col.last().id, 1);
}); });


test("#964 - collection.get return in consistent", function() { test("#964 - collection.get return in consistent", function() {
Expand Down

0 comments on commit 18fba57

Please sign in to comment.