Browse files

`store.unregister` now also accepts collections or a model type

  • Loading branch information...
1 parent 4d0b705 commit 4113c69d3752fcac75f7a1959c77349dd4672afa @PaulUithol committed Feb 3, 2014
Showing with 98 additions and 12 deletions.
  1. +43 −11 backbone-relational.js
  2. +55 −1 test/tests.js
View
54 backbone-relational.js
@@ -488,6 +488,7 @@
update: function( model ) {
var coll = this.getCollection( model );
+ // Register a model if it isn't yet (which happens if it was created without an id).
if ( !coll.contains( model ) ) {
this.register( model );
}
@@ -500,22 +501,46 @@
},
/**
- * Remove a 'model' from the store.
- * @param {Backbone.RelationalModel} model
- * @param {Backbone.Collection} [collection]
- * @param {Object} [options]
+ * Unregister from the store: a specific model, a collection, or a model type.
+ * @param {Backbone.RelationalModel|Backbone.RelationalModel.constructor|Backbone.Collection} type
*/
- unregister: function( model, collection, options ) {
- this.stopListening( model );
+ unregister: function( type ) {
+ var coll,
+ models;
- _.invoke( model.getRelations(), 'stopListening' );
+ if ( type instanceof Backbone.Model ) {
+ coll = this.getCollection( type );
+ models = [ type ];
+ }
+ else if ( type instanceof Backbone.Collection ) {
+ coll = this.getCollection( type.model );
+ models = _.clone( type.models );
@philfreo
Collaborator
philfreo added a note Feb 4, 2014

should you use type.clone() directly here since Backbone.Collection has a clone()?

@PaulUithol
Owner

Ah, didn't stop to think that one could be proxied by Collection as well. Would be just a bit nicer indeed.

@PaulUithol
Owner

Actually, that won't work here; coll.clone() would result in a new collection, while we just need an array of models here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ }
+ else {
+ coll = this.getCollection( type );
+ models = _.clone( coll.models );
+ }
- var coll = this.getCollection( model );
- if ( coll.get( model ) ) {
- coll.remove( model, options );
+ _.each( models, function( model ) {
+ this.stopListening( model );
+ _.invoke( model.getRelations(), 'stopListening' );
+ }, this );
+
+
+ // If we've unregistered an entire store collection, reset the collection (which is much faster).
+ // Otherwise, remove each model one by one.
+ if ( _.contains( this._collections, type ) ) {
+ coll.reset( [] );
}
else {
- coll.trigger( 'relational:remove', model, coll );
+ _.each( models, function( model ) {
+ if ( coll.get( model ) ) {
+ coll.remove( model );
+ }
+ else {
+ coll.trigger( 'relational:remove', model, coll );
+ }
+ }, this );
}
},
@@ -525,6 +550,12 @@
*/
reset: function() {
this.stopListening();
+
+ // Unregister each collection to remove event listeners
+ _.each( this._collections, function( coll ) {
+ this.unregister( coll );
+ }, this );
+
this._collections = [];
this._subModels = [];
this._modelScopes = [ exports ];
@@ -1478,6 +1509,7 @@
if ( !this._isInitialized && !this.isLocked() ) {
this.constructor.initializeModelHierarchy();
+ // Only register models that have an id. A model will be registered when/if it gets an id later on.
if ( newId || newId === 0 ) {
Backbone.Relational.store.register( this );
}
View
56 test/tests.js
@@ -649,6 +649,53 @@ $(document).ready(function() {
ok( !Backbone.Relational.store.getObjectByName( 'Person' ) );
});
+ test( "unregister", function() {
+ var animalStoreColl = Backbone.Relational.store.getCollection( Animal ),
+ animals = null,
+ animal = null;
+
+ // Single model
+ animal = new Animal( { id: 'a1' } );
+ ok( Backbone.Relational.store.find( Animal, 'a1' ) === animal );
+
+ Backbone.Relational.store.unregister( animal );
+ ok( Backbone.Relational.store.find( Animal, 'a1' ) === null );
+
+ animal = new Animal( { id: 'a2' } );
+ ok( Backbone.Relational.store.find( Animal, 'a2' ) === animal );
+
+ animal.trigger( 'relational:unregister', animal );
+ ok( Backbone.Relational.store.find( Animal, 'a2' ) === null );
+
+ ok( animalStoreColl.size() === 0 );
+
+ // Collection
+ animals = new AnimalCollection( [ { id: 'a3' }, { id: 'a4' } ] );
+ animal = animals.first();
+
+ ok( Backbone.Relational.store.find( Animal, 'a3' ) === animal );
+ ok( animalStoreColl.size() === 2 );
+
+ Backbone.Relational.store.unregister( animals );
+ ok( Backbone.Relational.store.find( Animal, 'a3' ) === null );
+
+ ok( animalStoreColl.size() === 0 );
+
+ // Store collection
+ animals = new AnimalCollection( [ { id: 'a5' }, { id: 'a6' } ] );
+ ok( animalStoreColl.size() === 2 );
+
+ Backbone.Relational.store.unregister( animalStoreColl );
+ ok( animalStoreColl.size() === 0 );
+
+ // Model type
+ animals = new AnimalCollection( [ { id: 'a7' }, { id: 'a8' } ] );
+ ok( animalStoreColl.size() === 2 );
+
+ Backbone.Relational.store.unregister( Animal );
+ ok( animalStoreColl.size() === 0 );
+ });
+
test( "`eventQueue` is unblocked again after a duplicate id error", 3, function() {
var node = new Node( { id: 1 } );
@@ -4588,12 +4635,15 @@ $(document).ready(function() {
});
var parents = new Parents();
+
parents.on('reset', function () {
var secs = (new Date() - start) / 1000;
console.log( 'data loaded in %s, addHasManyCount=%o, addHasOneCount=%o', secs, addHasManyCount, addHasOneCount );
});
parents.reset( preparedData );
+ //_.invoke( _.clone( parents.models ), 'destroy' );
+
/**
* Test 1
@@ -4604,12 +4654,15 @@ $(document).ready(function() {
var start = new Date();
var parents = new Parents();
+
parents.on('reset', function () {
var secs = (new Date() - start) / 1000;
console.log( 'data loaded in %s, addHasManyCount=%o, addHasOneCount=%o', secs, addHasManyCount, addHasOneCount );
});
parents.reset( data );
+ //_.invoke( _.clone( parents.models ), 'destroy' );
+
/**
* Test 2 (again)
@@ -4639,6 +4692,7 @@ $(document).ready(function() {
var secs = (new Date() - start) / 1000;
console.log( 'data loaded in %s, removeHasManyCount=%o, removeHasOneCount=%o', secs, removeHasManyCount, removeHasOneCount );
+ //_.invoke( _.clone( parents.models ), 'destroy' );
/**
* Test 1 (again)
@@ -4660,7 +4714,7 @@ $(document).ready(function() {
parents.remove( parents.models );
var secs = (new Date() - start) / 1000;
- console.log( 'data loaded in %s, removeHasManyCount=%o, removeHasOneCount=%o', secs, removeHasManyCount, removeHasOneCount );
+ console.log( 'data removed in %s, removeHasManyCount=%o, removeHasOneCount=%o', secs, removeHasManyCount, removeHasOneCount );
console.log( 'registerCount=%o, unregisterCount=%o', registerCount, unregisterCount );
});

0 comments on commit 4113c69

Please sign in to comment.