Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 66 additions & 3 deletions backbone-relational.js
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,28 @@
// Add this Relation to instance._relations
this.instance._relations[ this.key ] = this;

if(this.model.__modelId == null) {
if(window.__modelId == null) {
window.__modelId = 0;
}
this.model.__modelId = window.__modelId++;
}

var reverseIndexKey = this.model.__modelId + ":" + this.key;
if(this.relatedCollection._reverseIndexes == null) this.relatedCollection._reverseIndexes = {};
this.reverseIndex = this.relatedCollection._reverseIndexes[reverseIndexKey];
if(this.reverseIndex == null) {
this.reverseIndex = this.relatedCollection._reverseIndexes[reverseIndexKey] = {};
this.relatedCollection.on("relational:add relational:change:id", _.bind(function(model, coll, opts){
var id = model.get(model.idAttribute);
if(id != null) {
_.forEach(this.reverseIndex[id], function(obj) {
obj._relations[this.key].tryAddRelated(model, coll, opts);
}, this);
}
}, this));
}

this.initialize( opts );

if ( this.options.autoFetch ) {
Expand All @@ -642,7 +664,6 @@

// When 'relatedModel' are created or destroyed, check if it affects this relation.
this.listenTo( this.instance, 'destroy', this.destroy )
.listenTo( this.relatedCollection, 'relational:add relational:change:id', this.tryAddRelated )
.listenTo( this.relatedCollection, 'relational:remove', this.removeRelated )
}
};
Expand Down Expand Up @@ -784,6 +805,11 @@
var related = this.findRelated( opts );
this.setRelated( related );

if(this.keyId != null) {
var index = this.reverseIndex[this.keyId] || (this.reverseIndex[this.keyId] = {});
index[this.instance.cid] = this.instance;
}

// Notify new 'related' object of the new relation.
_.each( this.getReverseRelations(), function( relation ) {
relation.addRelated( this.instance, opts );
Expand Down Expand Up @@ -847,20 +873,36 @@
this.setKeyContents( attr );
var related = this.findRelated( options );
this.setRelated( related );
var id = this.related != null ? this.related.get(this.related.idAttribute) : null;
if(this.reverseIndex != null && this.related != null && id != null) {
var reverseIndex = this.reverseIndex[id] || (this.reverseIndex[id] = {});
reverseIndex[this.instance.cid] = this.instance;
}
}

// Notify old 'related' object of the terminated relation
if ( oldRelated && this.related !== oldRelated ) {
_.each( this.getReverseRelations( oldRelated ), function( relation ) {
relation.removeRelated( this.instance, null, options );
var id = this.instance.get(this.instance.idAttribute);
if(this.reverseIndex != null && id != null) {
var reverseIndex = relation.reverseIndex[id] ||
(relation.reverseIndex[id] = {});
delete reverseIndex[relation.instance.cid];
}
relation.removeRelated( this.instance, null, options );
}, this );
}

// Notify new 'related' object of the new relation. Note we do re-apply even if this.related is oldRelated;
// that can be necessary for bi-directional relations if 'this.instance' was created after 'this.related'.
// In that case, 'this.instance' will already know 'this.related', but the reverse might not exist yet.
_.each( this.getReverseRelations(), function( relation ) {
relation.addRelated( this.instance, options );
var id = this.instance.get(this.instance.idAttribute);
if(id != null && relation.reverseIndex != null) {
var reverseIndex = relation.reverseIndex[id] || (relation.reverseIndex[id] = {});
reverseIndex[relation.instance.cid] = this.instance;
}
relation.addRelated( this.instance, options );
}, this );

// Fire the 'change:<key>' event if 'related' was updated
Expand Down Expand Up @@ -936,6 +978,11 @@
throw new Error( '`collectionType` must inherit from Backbone.Collection' );
}

_.forEach(this.keyIds, function(id) {
var index = this.reverseIndex[id] || (this.reverseIndex[id] = {});
index[this.instance.cid] = this.instance;
}, this);

var related = this.findRelated( opts );
this.setRelated( related );
},
Expand Down Expand Up @@ -1051,6 +1098,7 @@
}
}, this );
}

},

/**
Expand All @@ -1059,12 +1107,27 @@
*/
onChange: function( model, attr, options ) {
options = options ? _.clone( options ) : {};

if(this.reverseIndex != null) {
_.forEach(this.keyIds, function (keyId) {
var index = this.reverseIndex[keyId];
delete index[this.instance.cid];
}, this);
}

this.setKeyContents( attr );
this.changed = false;

var related = this.findRelated( options );
this.setRelated( related );

if(this.reverseIndex != null && this.keyIds != null) {
_.forEach(this.keyIds, function (keyId) {
var index = this.reverseIndex[keyId] || (this.reverseIndex[keyId] = {});
index[this.instance.cid] = this.instance;
}, this);
}

if ( !options.silent ) {
var dit = this;
Backbone.Relational.eventQueue.add( function() {
Expand Down
3 changes: 2 additions & 1 deletion test/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -3454,7 +3454,8 @@ $(document).ready(function() {
]);

equal(animals.at(0).id, 'lion-1');
deepEqual(events, ['add', 'sort', 'add', 'sort']);
equal(animals.at(1).id, 'lion-2');
deepEqual(events, ['add', 'add', 'sort']);
});


Expand Down