emberjs/data — pull request #715 by sandstrom (2013-02-09 16:10:17+00:00)
Title: Add missing `suspendRelationshipsObservers` for belongsTo in DS.RelationshipChangeRemove

If relationship observers aren't suspended one-to-one relationships end up in an infinite loop when a removal is synchronised.

This should solve https://github.com/emberjs/data/issues/671.

*I think this is just an oversight, since observers are suspended for all other types of relationship changes (see below):*

DS.RelationshipChangeRemove.prototype.changeType = "remove";
DS.RelationshipChangeRemove.prototype.sync = function() {
var secondRecordName = this.getSecondRecordName(),
firstRecordName = this.getFirstRecordName(),
firstRecord = this.getFirstRecord(),
secondRecord = this.getSecondRecord();

//Ember.assert("You specified a hasMany (" + hasManyName + ") on " + (!belongsToName && (newParent || oldParent || this.lastParent).constructor) + " but did not specify an inverse belongsTo on " + child.constructor, belongsToName);
//Ember.assert("You specified a belongsTo (" + belongsToName + ") on " + child.constructor + " but did not specify an inverse hasMany on " + (!hasManyName && (newParent || oldParent || this.lastParentRecord).constructor), hasManyName);

var transaction = this.ensureSameTransaction(firstRecord, secondRecord, secondRecordName, firstRecordName);
transaction.relationshipBecameDirty(this);

this.callChangeEvents();

if (secondRecord && firstRecord) {
if(this.secondRecordKind === "belongsTo"){
set(secondRecord, secondRecordName, null); // <======= OBSERVERS AREN'T SUSPENDED
}
else if(this.secondRecordKind === "hasMany"){
secondRecord.suspendRelationshipObservers(function(){
get(secondRecord, secondRecordName).removeObject(firstRecord);
});
}
}

if (firstRecord && get(firstRecord, firstRecordName)) {
if(this.firstRecordKind === "belongsTo"){
firstRecord.suspendRelationshipObservers(function(){
set(firstRecord, firstRecordName, null);
});
}
else if(this.firstdRecordKind === "hasMany"){
firstRecord.suspendRelationshipObservers(function(){
get(firstRecord, firstRecordName).removeObject(secondRecord);
});
}
}

this.coalesce();
};