Skip to content
Browse files

Fixed bugs with rolling back relationship changes

  • Loading branch information...
1 parent 89ecd9f commit 019ea76bfd0cf6931d7cbad1a726710b895f9789 tomhuda committed Aug 14, 2012
View
22 packages/ember-data/lib/system/associations/one_to_many_change.js
@@ -126,17 +126,6 @@ DS.OneToManyChange.prototype = {
// infinite loop.
- // Only set the belongsTo on the child if it is not already the
- // newParent. This happens if the change happened from the
- // ManyArray side.
- if (get(child, belongsToName) !== newParent) {
- set(child, belongsToName, newParent);
- }
-
- if (get(child, 'isLoaded')) {
- child.addDirtyFactor(belongsToName);
- }
-
// If there is an `oldParent`, use the idempotent `removeObject`
// to ensure that the record is no longer in its ManyArray. The
// `removeObject` method only has an effect if:
@@ -164,6 +153,17 @@ DS.OneToManyChange.prototype = {
}
}
+ // Only set the belongsTo on the child if it is not already the
+ // newParent. This happens if the change happened from the
+ // ManyArray side.
+ if (get(child, belongsToName) !== newParent) {
+ set(child, belongsToName, newParent);
+ }
+
+ if (get(child, 'isLoaded')) {
+ child.addDirtyFactor(belongsToName);
+ }
+
// If this change is later reversed (A->B followed by B->A),
// we will need to remove the child from this parent. Save
// it off as `lastParent` so we can do that.
View
29 packages/ember-data/lib/system/model/model.js
@@ -104,6 +104,8 @@ DS.Model = Ember.Object.extend(Ember.Evented, {
this.eachAssociation(function(name, relationship) {
if (relationship.kind === 'belongsTo') {
set(this, name, null);
+ } else if (relationship.kind === 'hasMany') {
+ get(this, name).clear();
}
}, this);
},
@@ -243,15 +245,34 @@ DS.Model = Ember.Object.extend(Ember.Evented, {
});
},
+ /**
+ @private
+
+ The goal of this method is to temporarily disable specific observers
+ that take action in response to application changes.
+
+ This allows the system to make changes (such as materialization and
+ rollback) that should not trigger secondary behavior (such as setting an
+ inverse relationship or marking records as dirty).
+
+ The specific implementation will likely change as Ember proper provides
+ better infrastructure for suspending groups of observers, and if Array
+ observation becomes more unified with regular observers.
+ */
suspendAssociationObservers: function(callback, binding) {
var observers = get(this.constructor, 'associationNames').belongsTo;
var self = this;
- Ember._suspendObservers(self, observers, null, 'belongsToDidChange', function() {
- Ember._suspendBeforeObservers(self, observers, null, 'belongsToWillChange', function() {
- callback.call(binding || self);
+ try {
+ this._suspendedAssociations = true;
+ Ember._suspendObservers(self, observers, null, 'belongsToDidChange', function() {
+ Ember._suspendBeforeObservers(self, observers, null, 'belongsToWillChange', function() {
+ callback.call(binding || self);
+ });
});
- });
+ } finally {
+ this._suspendedAssociations = false;
+ }
},
becameInFlight: function() {
View
5 packages/ember-data/lib/system/model/states.js
@@ -449,8 +449,9 @@ createdState.states.uncommitted.reopen({
record.clearRelationships();
record.withTransaction(function(t) {
- t.recordBecameClean('created', record);
+ t.recordIsMoving('created', record);
});
+
manager.transitionTo('deleted.saved');
}
});
@@ -469,7 +470,7 @@ updatedState.states.uncommitted.reopen({
get(manager, 'record').clearRelationships();
record.withTransaction(function(t) {
- t.recordBecameClean('updated', record);
+ t.recordIsMoving('updated', record);
});
manager.transitionTo('deleted');
View
15 packages/ember-data/lib/system/record_arrays/many_array.js
@@ -35,10 +35,7 @@ var get = Ember.get, set = Ember.set;
*/
DS.ManyArray = DS.RecordArray.extend({
init: function() {
- //set(this, 'stateManager', DS.ManyArrayStateManager.create({ manyArray: this }));
-
this._super.apply(this, arguments);
- this._initted = true;
this._changesToSync = Ember.OrderedSet.create();
},
@@ -91,10 +88,10 @@ DS.ManyArray = DS.RecordArray.extend({
},
arrayContentWillChange: function(index, removed, added) {
- if (this._initted) {
@lukemelia
Ember.js member
lukemelia added a note Aug 16, 2012

What made this guard unnecessary? Without it, I am seeing an error on a undefined "owner" property in arrayContentWillChange

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
- var owner = get(this, 'owner'),
- name = get(this, 'name');
+ var owner = get(this, 'owner'),
+ name = get(this, 'name');
+ if (!owner._suspendedAssociations) {
// This code is the first half of code that continues inside
// of arrayContentDidChange. It gets or creates a change from
// the child object, adds the current owner as the old
@@ -123,10 +120,10 @@ DS.ManyArray = DS.RecordArray.extend({
arrayContentDidChange: function(index, removed, added) {
this._super.apply(this, arguments);
- if (this._initted) {
- var owner = get(this, 'owner'),
- name = get(this, 'name');
+ var owner = get(this, 'owner'),
+ name = get(this, 'name');
+ if (!owner._suspendedAssociations) {
// This code is the second half of code that started in
// `arrayContentWillChange`. It gets or creates a change
// from the child object, and adds the current owner as
View
5 packages/ember-data/lib/system/transaction.js
@@ -357,6 +357,11 @@ DS.Transaction = Ember.Object.extend({
this.addToBucket('inflight', record);
},
+ recordIsMoving: function(kind, record) {
+ this.removeFromBucket(kind, record);
+ this.addToBucket('clean', record);
+ },
+
/**
@private
View
550 packages/ember-data/tests/integration/rollback_test.js
@@ -8,11 +8,15 @@ module("Rolling back transactions", {
title: DS.attr('string')
});
+ Post.toString = function() { return "Post"; };
+
Comment = DS.Model.extend({
title: DS.attr('string'),
post: DS.belongsTo(Post)
});
+ Comment.toString = function() { return "Comment"; };
+
Post.reopen({
comments: DS.hasMany(Comment)
});
@@ -54,6 +58,8 @@ test("A loaded record in a transaction with changed attributes should revert to
testSetAndRollback(post, 'title', "Developing Interplanetary-Scale Apps");
});
+// UPDATED
+
test("A loaded record in a transaction with a changed belongsTo should revert to the old relationship when the transaction is rolled back. (A=>null)", function() {
store.load(Post, { id: 1, title: "My Darkest Node.js Fantasies", comments: [ 1, 2 ] });
store.load(Comment, { id: 1, title: "I don't see the appeal of Rails these days when Node.js and Django are both as mature and inherently more scalable than Rails", post: 1 });
@@ -79,7 +85,6 @@ test("A loaded record in a transaction with a changed belongsTo should revert to
equal(comment1.get('post'), null, "precond - property reflects changed value");
deepEqual(post.get('comments').toArray(), [ comment2 ], "precond - property reflects changed value");
- window.billy = true;
transaction.rollback();
ok(!post.get('isDirty'), "record should not be dirty after rollback");
@@ -88,11 +93,546 @@ test("A loaded record in a transaction with a changed belongsTo should revert to
equal(comment1.get('post'), post, "property is rolled back to its original value");
deepEqual(post.get('comments').toArray(), [ comment1, comment2 ], "property is rolled back to its original value");
});
-//test("A loaded record in a transaction with a changed hasMany should revert to the old relationship when the transaction is rolled back.");
-//test("A created record in a transaction with changed attributes should revert to the old attributes when the transaction is rolled back.");
-//test("A created record in a transaction with a changed belongsTo should revert to the old relationship when the transaction is rolled back.");
-//test("A created record in a transaction with a changed hasMany should revert to the old relationship when the transaction is rolled back.");
+test("A loaded record in a transaction with a changed belongsTo should revert to the old relationship when the transaction is rolled back. (null=>A)", function() {
+ store.load(Post, { id: 1, title: "My Darkest Node.js Fantasies" });
+ store.load(Comment, { id: 1, title: "I don't see the appeal of Rails these days when Node.js and Django are both as mature and inherently more scalable than Rails" });
+ store.load(Comment, { id: 2, title: "I was skeptical about http://App.net before I paid the $$, but now I am all excited about it." });
+
+ var post = store.find(Post, 1);
+ var comment1 = store.find(Comment, 1);
+ var comment2 = store.find(Comment, 2);
+
+ var oldValue = comment1.get('post');
+
+ equal(oldValue, null, "precond - the original value is null");
+ deepEqual(post.get('comments').toArray(), [ ], "precond - the original value is an empty array");
+
+ var transaction = store.transaction();
+ transaction.add(post);
+
+ ok(!post.get('isDirty'), "precond - record should not yet be dirty");
+ ok(!comment1.get('isDirty'), "precond - record should not yet be dirty");
+
+ comment1.set('post', post);
+
+ ok(post.get('isDirty'), "precond - record should be dirty after change");
+ ok(comment1.get('isDirty'), "precond - record should be dirty after change");
+
+ equal(comment1.get('post'), post, "precond - property reflects changed value");
+ deepEqual(post.get('comments').toArray(), [ comment1 ], "precond - property reflects changed value");
+
+ transaction.rollback();
+
+ ok(!post.get('isDirty'), "record should not be dirty after rollback");
+ ok(!comment1.get('isDirty'), "record should not be dirty after rollback");
+
+ equal(comment1.get('post'), null, "property is rolled back to its original value");
+ deepEqual(post.get('comments').toArray(), [ ], "property is rolled back to its original value");
+});
+
+test("A loaded record in a transaction with a changed belongsTo should revert to the old relationship when the transaction is rolled back. (A=>B)", function() {
+ store.load(Post, { id: 1, title: "My Darkest Node.js Fantasies", comments: [ 1, 2 ] });
+ store.load(Post, { id: 2, title: "VIM for iPad Best Practices" });
+ store.load(Comment, { id: 1, title: "I don't see the appeal of Rails these days when Node.js and Django are both as mature and inherently more scalable than Rails", post: 1 });
+ store.load(Comment, { id: 2, title: "I was skeptical about http://App.net before I paid the $$, but now I am all excited about it.", post: 1 });
+
+ var post = store.find(Post, 1);
+ var post2 = store.find(Post, 2);
+ var comment1 = store.find(Comment, 1);
+ var comment2 = store.find(Comment, 2);
+
+ var oldValue = comment1.get('post');
+
+ equal(oldValue, post, "precond - the original value is null");
+ deepEqual(post.get('comments').toArray(), [ comment1, comment2 ], "precond - the original value is a list of comments");
+
+ var transaction = store.transaction();
+ transaction.add(post);
+
+ ok(!post.get('isDirty'), "precond - record should not yet be dirty");
+ ok(!comment1.get('isDirty'), "precond - record should not yet be dirty");
+
+ comment1.set('post', post2);
+
+ ok(post.get('isDirty'), "precond - record should be dirty after change");
+ ok(post2.get('isDirty'), "precond - record should be dirty after change");
+ ok(comment1.get('isDirty'), "precond - record should be dirty after change");
+
+ equal(comment1.get('post'), post2, "precond - property reflects changed value");
+ deepEqual(post.get('comments').toArray(), [ comment2 ], "precond - property reflects changed value");
+ deepEqual(post2.get('comments').toArray(), [ comment1 ], "precond - property reflects changed value");
+
+ transaction.rollback();
+
+ ok(!post.get('isDirty'), "record should not be dirty after rollback");
+ ok(!post2.get('isDirty'), "record should not be dirty after rollback");
+ ok(!comment1.get('isDirty'), "record should not be dirty after rollback");
+
+ equal(comment1.get('post'), post, "property is rolled back to its original value");
+ deepEqual(post.get('comments').toArray(), [ comment1, comment2 ], "property is rolled back to its original value");
+});
+
+test("A loaded record in a transaction with a changed hasMany should revert to the old relationship when the transaction is rolled back. (A=>null)", function() {
+ store.load(Post, { id: 1, title: "My Darkest Node.js Fantasies", comments: [ 1, 2 ] });
+ store.load(Comment, { id: 1, title: "I don't see the appeal of Rails these days when Node.js and Django are both as mature and inherently more scalable than Rails", post: 1 });
+ store.load(Comment, { id: 2, title: "I was skeptical about http://App.net before I paid the $$, but now I am all excited about it.", post: 1 });
+
+ var post = store.find(Post, 1);
+ var comment1 = store.find(Comment, 1);
+ var comment2 = store.find(Comment, 2);
+
+ var oldValue = comment1.get('post');
+
+ var transaction = store.transaction();
+ transaction.add(post);
+
+ ok(!post.get('isDirty'), "precond - record should not yet be dirty");
+ ok(!comment1.get('isDirty'), "precond - record should not yet be dirty");
+
+ post.get('comments').removeObject(comment1);
+
+ ok(post.get('isDirty'), "precond - record should be dirty after change");
+ ok(comment1.get('isDirty'), "precond - record should be dirty after change");
+
+ equal(comment1.get('post'), null, "precond - property reflects changed value");
+ deepEqual(post.get('comments').toArray(), [ comment2 ], "precond - property reflects changed value");
+
+ transaction.rollback();
+
+ ok(!post.get('isDirty'), "record should not be dirty after rollback");
+ ok(!comment1.get('isDirty'), "record should not be dirty after rollback");
+
+ equal(comment1.get('post'), post, "property is rolled back to its original value");
+ deepEqual(post.get('comments').toArray(), [ comment1, comment2 ], "property is rolled back to its original value");
+});
+
+test("A loaded record in a transaction with a changed hasMany should revert to the old relationship when the transaction is rolled back. (null=>A)", function() {
+ store.load(Post, { id: 1, title: "My Darkest Node.js Fantasies" });
+ store.load(Comment, { id: 1, title: "I don't see the appeal of Rails these days when Node.js and Django are both as mature and inherently more scalable than Rails" });
+ store.load(Comment, { id: 2, title: "I was skeptical about http://App.net before I paid the $$, but now I am all excited about it." });
+
+ var post = store.find(Post, 1);
+ var comment1 = store.find(Comment, 1);
+ var comment2 = store.find(Comment, 2);
+
+ var oldValue = comment1.get('post');
+
+ equal(oldValue, null, "precond - the original value is null");
+ deepEqual(post.get('comments').toArray(), [ ], "precond - the original value is an empty array");
+
+ var transaction = store.transaction();
+ transaction.add(post);
+
+ ok(!post.get('isDirty'), "precond - record should not yet be dirty");
+ ok(!comment1.get('isDirty'), "precond - record should not yet be dirty");
+
+ post.get('comments').addObject(comment1);
+
+ ok(post.get('isDirty'), "precond - record should be dirty after change");
+ ok(comment1.get('isDirty'), "precond - record should be dirty after change");
+
+ equal(comment1.get('post'), post, "precond - property reflects changed value");
+ deepEqual(post.get('comments').toArray(), [ comment1 ], "precond - property reflects changed value");
+
+ transaction.rollback();
+
+ ok(!post.get('isDirty'), "record should not be dirty after rollback");
+ ok(!comment1.get('isDirty'), "record should not be dirty after rollback");
+
+ equal(comment1.get('post'), null, "property is rolled back to its original value");
+ deepEqual(post.get('comments').toArray(), [ ], "property is rolled back to its original value");
+});
+
+test("A loaded record in a transaction with a changed hasMany should revert to the old relationship when the transaction is rolled back. (A=>B)", function() {
+ store.load(Post, { id: 1, title: "My Darkest Node.js Fantasies", comments: [ 1, 2 ] });
+ store.load(Post, { id: 2, title: "VIM for iPad Best Practices" });
+ store.load(Comment, { id: 1, title: "I don't see the appeal of Rails these days when Node.js and Django are both as mature and inherently more scalable than Rails", post: 1 });
+ store.load(Comment, { id: 2, title: "I was skeptical about http://App.net before I paid the $$, but now I am all excited about it.", post: 1 });
+
+ var post = store.find(Post, 1);
+ var post2 = store.find(Post, 2);
+ var comment1 = store.find(Comment, 1);
+ var comment2 = store.find(Comment, 2);
+
+ var oldValue = comment1.get('post');
+
+ equal(oldValue, post, "precond - the original value is null");
+ deepEqual(post.get('comments').toArray(), [ comment1, comment2 ], "precond - the original value is a list of comments");
+
+ var transaction = store.transaction();
+ transaction.add(post);
+
+ ok(!post.get('isDirty'), "precond - record should not yet be dirty");
+ ok(!comment1.get('isDirty'), "precond - record should not yet be dirty");
+
+ post.get('comments').removeObject(comment1);
+ post2.get('comments').addObject(comment1);
+
+ ok(post.get('isDirty'), "precond - record should be dirty after change");
+ ok(post2.get('isDirty'), "precond - record should be dirty after change");
+ ok(comment1.get('isDirty'), "precond - record should be dirty after change");
+
+ equal(comment1.get('post'), post2, "precond - property reflects changed value");
+ deepEqual(post.get('comments').toArray(), [ comment2 ], "precond - property reflects changed value");
+ deepEqual(post2.get('comments').toArray(), [ comment1 ], "precond - property reflects changed value");
+
+ transaction.rollback();
+
+ ok(!post.get('isDirty'), "record should not be dirty after rollback");
+ ok(!post2.get('isDirty'), "record should not be dirty after rollback");
+ ok(!comment1.get('isDirty'), "record should not be dirty after rollback");
+
+ equal(comment1.get('post'), post, "property is rolled back to its original value");
+ deepEqual(post.get('comments').toArray(), [ comment1, comment2 ], "property is rolled back to its original value");
+});
+
+test("A loaded record in a transaction with a changed hasMany (without first removing) should revert to the old relationship when the transaction is rolled back. (A=>B)", function() {
+ store.load(Post, { id: 1, title: "My Darkest Node.js Fantasies", comments: [ 1, 2 ] });
+ store.load(Post, { id: 2, title: "VIM for iPad Best Practices" });
+ store.load(Comment, { id: 1, title: "I don't see the appeal of Rails these days when Node.js and Django are both as mature and inherently more scalable than Rails", post: 1 });
+ store.load(Comment, { id: 2, title: "I was skeptical about http://App.net before I paid the $$, but now I am all excited about it.", post: 1 });
+
+ var post = store.find(Post, 1);
+ var post2 = store.find(Post, 2);
+ var comment1 = store.find(Comment, 1);
+ var comment2 = store.find(Comment, 2);
+
+ var oldValue = comment1.get('post');
+
+ equal(oldValue, post, "precond - the original value is null");
+ deepEqual(post.get('comments').toArray(), [ comment1, comment2 ], "precond - the original value is a list of comments");
+
+ var transaction = store.transaction();
+ transaction.add(post);
+
+ ok(!post.get('isDirty'), "precond - record should not yet be dirty");
+ ok(!comment1.get('isDirty'), "precond - record should not yet be dirty");
+
+ post2.get('comments').addObject(comment1);
+
+ ok(post.get('isDirty'), "precond - record should be dirty after change");
+ ok(post2.get('isDirty'), "precond - record should be dirty after change");
+ ok(comment1.get('isDirty'), "precond - record should be dirty after change");
+
+ equal(comment1.get('post'), post2, "precond - property reflects changed value");
+ deepEqual(post.get('comments').toArray(), [ comment2 ], "precond - property reflects changed value");
+ deepEqual(post2.get('comments').toArray(), [ comment1 ], "precond - property reflects changed value");
+
+ transaction.rollback();
+
+ ok(!post.get('isDirty'), "record should not be dirty after rollback");
+ ok(!post2.get('isDirty'), "record should not be dirty after rollback");
+ ok(!comment1.get('isDirty'), "record should not be dirty after rollback");
+
+ equal(comment1.get('post'), post, "property is rolled back to its original value");
+ deepEqual(post.get('comments').toArray(), [ comment1, comment2 ], "property is rolled back to its original value");
+});
+
+// CREATED - Changing belongsTo
+
+test("A created record in a transaction with a changed belongsTo (child is newly created, but parent is not) should revert to the old relationship when the transaction is rolled back. (null=>A)", function() {
+ store.load(Post, { id: 1, title: "My Darkest Node.js Fantasies", comments: [ 2 ] });
+ store.load(Comment, { id: 2, title: "I don't see the appeal of Rails these days when Node.js and Django are both as mature and inherently more scalable than Rails", post: 1 });
+
+ var transaction = store.transaction();
+
+ var post = store.find(Post, 1);
+ var comment1 = transaction.createRecord(Comment, { title: "I don't see the appeal of Rails these days when Node.js and Django are both as mature and inherently more scalable than Rails" });
+ var comment2 = store.find(Comment, 2);
+
+ var oldValue = comment1.get('post');
+
+ equal(oldValue, null, "precond - the original value is null");
+ deepEqual(post.get('comments').toArray(), [ comment2 ], "precond - the original value is a list of comments");
+
+ transaction.add(post);
+
+ comment1.set('post', post);
+ equal(comment1.get('post'), post, "precond - the new value is the post");
+ deepEqual(post.get('comments').toArray(), [ comment2, comment1 ], "precond - the new value is a list of comments");
+
+ ok(post.get('isDirty'), "precond - record should be dirty");
+ ok(comment1.get('isDirty'), "precond - record should be dirty");
+
+ transaction.rollback();
+
+ ok(!post.get('isDirty'), "record should not be dirty after rollback");
+ ok(!comment1.get('isDirty'), "record should not be dirty after rollback");
+
+ equal(comment1.get('post'), null, "property is rolled back to its original value");
+ deepEqual(post.get('comments').toArray(), [ comment2 ], "property is rolled back to its original value");
+});
+
+test("A loaded record in a transaction with a changed belongsTo (parent is newly created, but child is not) should revert to the old relationship when the transaction is rolled back. (null=>A)", function() {
+ var transaction = store.transaction();
+
+ store.load(Comment, { id: 1, title: "I don't see the appeal of Rails these days when Node.js and Django are both as mature and inherently more scalable than Rails" });
+ store.load(Comment, { id: 2, title: "I was skeptical about http://App.net before I paid the $$, but now I am all excited about it." });
+
+ var post = transaction.createRecord(Post, { title: "My Darkest Node.js Fantasies" });
+ var comment1 = store.find(Comment, 1);
+ var comment2 = store.find(Comment, 2);
+
+ var oldValue = comment1.get('post');
+
+ equal(oldValue, null, "precond - the original value is null");
+ deepEqual(post.get('comments').toArray(), [ ], "precond - the original value is an empty array");
+
+ ok(post.get('isDirty'), "precond - record should be dirty");
+ ok(!comment1.get('isDirty'), "precond - record should not yet be dirty");
+
+ comment1.set('post', post);
+
+ ok(post.get('isDirty'), "precond - record should be dirty after change");
+ ok(comment1.get('isDirty'), "precond - record should be dirty after change");
+
+ equal(comment1.get('post'), post, "precond - property reflects changed value");
+ deepEqual(post.get('comments').toArray(), [ comment1 ], "precond - property reflects changed value");
+
+ transaction.rollback();
+
+ ok(!post.get('isDirty'), "record should not be dirty after rollback");
+ ok(!comment1.get('isDirty'), "record should not be dirty after rollback");
+
+ equal(comment1.get('post'), null, "property is rolled back to its original value");
+ deepEqual(post.get('comments').toArray(), [ ], "property is rolled back to its original value");
+});
+
+test("A loaded record in a transaction with a changed belongsTo (parent and child are both newly created) should revert to the old relationship when the transaction is rolled back. (A=>B)", function() {
+ var transaction = store.transaction();
+
+ var post = transaction.createRecord(Post, { title: "My Darkest Node.js Fantasies" });
+ var comment1 = transaction.createRecord(Comment, { title: "I don't see the appeal of Rails these days when Node.js and Django are both as mature and inherently more scalable than Rails" });
+
+ var oldValue = comment1.get('post');
+
+ equal(oldValue, null, "precond - the original value is null");
+ deepEqual(post.get('comments').toArray(), [ ], "precond - the original value is an empty list of comments");
+
+ ok(post.get('isDirty'), "precond - record should be dirty");
+ ok(comment1.get('isDirty'), "precond - record should be dirty");
+
+ comment1.set('post', post);
+
+ ok(post.get('isDirty'), "precond - record should be dirty after change");
+ ok(comment1.get('isDirty'), "precond - record should be dirty after change");
+
+ equal(comment1.get('post'), post, "precond - property reflects changed value");
+ deepEqual(post.get('comments').toArray(), [ comment1 ], "precond - property reflects changed value");
+
+ transaction.rollback();
+
+ ok(!post.get('isDirty'), "record should not be dirty after rollback");
+ ok(!comment1.get('isDirty'), "record should not be dirty after rollback");
+
+ equal(comment1.get('post'), null, "property is rolled back to its original value");
+ deepEqual(post.get('comments').toArray(), [ ], "property is rolled back to its original value");
+});
+
+// CREATED - Changing hasMany
+
+test("A created record in a transaction with a changed hasMany (child is newly created, but parent is not) should revert to the old relationship when the transaction is rolled back. (null=>A)", function() {
+ store.load(Post, { id: 1, title: "My Darkest Node.js Fantasies", comments: [ 2 ] });
+ store.load(Comment, { id: 2, title: "I don't see the appeal of Rails these days when Node.js and Django are both as mature and inherently more scalable than Rails", post: 1 });
+
+ var transaction = store.transaction();
+
+ var post = store.find(Post, 1);
+ var comment1 = transaction.createRecord(Comment, { title: "I don't see the appeal of Rails these days when Node.js and Django are both as mature and inherently more scalable than Rails" });
+ var comment2 = store.find(Comment, 2);
+
+ var oldValue = comment1.get('post');
+
+ equal(oldValue, null, "precond - the original value is null");
+ deepEqual(post.get('comments').toArray(), [ comment2 ], "precond - the original value is a list of comments");
+
+ transaction.add(post);
+
+ post.get('comments').addObject(comment1);
+
+ equal(comment1.get('post'), post, "precond - the new value is the post");
+ deepEqual(post.get('comments').toArray(), [ comment2, comment1 ], "precond - the new value is a list of comments");
+
+ ok(post.get('isDirty'), "precond - record should be dirty");
+ ok(comment1.get('isDirty'), "precond - record should be dirty");
+
+ transaction.rollback();
+
+ ok(!post.get('isDirty'), "record should not be dirty after rollback");
+ ok(!comment1.get('isDirty'), "record should not be dirty after rollback");
+
+ equal(comment1.get('post'), null, "property is rolled back to its original value");
+ deepEqual(post.get('comments').toArray(), [ comment2 ], "property is rolled back to its original value");
+});
+
+test("A created record in a transaction with a changed belongsTo (parent is newly created, but child is not) should revert to the old relationship when the transaction is rolled back. (null=>A)", function() {
+ var transaction = store.transaction();
+
+ store.load(Comment, { id: 1, title: "I don't see the appeal of Rails these days when Node.js and Django are both as mature and inherently more scalable than Rails" });
+ store.load(Comment, { id: 2, title: "I was skeptical about http://App.net before I paid the $$, but now I am all excited about it." });
+
+ var post = transaction.createRecord(Post, { title: "My Darkest Node.js Fantasies" });
+ var comment1 = store.find(Comment, 1);
+ var comment2 = store.find(Comment, 2);
+
+ var oldValue = comment1.get('post');
+
+ equal(oldValue, null, "precond - the original value is null");
+ deepEqual(post.get('comments').toArray(), [ ], "precond - the original value is an empty array");
+
+ ok(post.get('isDirty'), "precond - record should be dirty");
+ ok(!comment1.get('isDirty'), "precond - record should not yet be dirty");
+
+ post.get('comments').addObject(comment1);
+
+ ok(post.get('isDirty'), "precond - record should be dirty after change");
+ ok(comment1.get('isDirty'), "precond - record should be dirty after change");
+
+ equal(comment1.get('post'), post, "precond - property reflects changed value");
+ deepEqual(post.get('comments').toArray(), [ comment1 ], "precond - property reflects changed value");
+
+ transaction.rollback();
+
+ ok(!post.get('isDirty'), "record should not be dirty after rollback");
+ ok(!comment1.get('isDirty'), "record should not be dirty after rollback");
+
+ equal(comment1.get('post'), null, "property is rolled back to its original value");
+ deepEqual(post.get('comments').toArray(), [ ], "property is rolled back to its original value");
+});
+
+test("A created record in a transaction with a changed belongsTo (parent and child are both newly created) should revert to the old relationship when the transaction is rolled back. (A=>B)", function() {
+ var transaction = store.transaction();
+
+ var post = transaction.createRecord(Post, { title: "My Darkest Node.js Fantasies" });
+ var comment1 = transaction.createRecord(Comment, { title: "I don't see the appeal of Rails these days when Node.js and Django are both as mature and inherently more scalable than Rails" });
+
+ var oldValue = comment1.get('post');
+
+ equal(oldValue, null, "precond - the original value is null");
+ deepEqual(post.get('comments').toArray(), [ ], "precond - the original value is an empty list of comments");
+
+ ok(post.get('isDirty'), "precond - record should be dirty");
+ ok(comment1.get('isDirty'), "precond - record should be dirty");
+
+ post.get('comments').addObject(comment1);
+
+ ok(post.get('isDirty'), "precond - record should be dirty after change");
+ ok(comment1.get('isDirty'), "precond - record should be dirty after change");
+
+ equal(comment1.get('post'), post, "precond - property reflects changed value");
+ deepEqual(post.get('comments').toArray(), [ comment1 ], "precond - property reflects changed value");
+
+ transaction.rollback();
+
+ ok(!post.get('isDirty'), "record should not be dirty after rollback");
+ ok(!comment1.get('isDirty'), "record should not be dirty after rollback");
+
+ equal(comment1.get('post'), null, "property is rolled back to its original value");
+ deepEqual(post.get('comments').toArray(), [ ], "property is rolled back to its original value");
+});
+
+// DELETED
+
+test("A deleted record should be restored to a hasMany relationship if the transaction is rolled back", function() {
+ store.load(Post, { id: 1, title: "My Darkest Node.js Fantasies", comments: [ 1, 2 ] });
+ store.load(Comment, { id: 1, title: "I don't see the appeal of Rails these days when Node.js and Django are both as mature and inherently more scalable than Rails", post: 1 });
+ store.load(Comment, { id: 2, title: "I was skeptical about http://App.net before I paid the $$, but now I am all excited about it.", post: 1 });
+
+ var post = store.find(Post, 1);
+ var comment1 = store.find(Comment, 1);
+ var comment2 = store.find(Comment, 2);
+
+ var oldValue = comment1.get('post');
+
+ var transaction = store.transaction();
+ transaction.add(post);
+
+ ok(!post.get('isDirty'), "precond - record should not yet be dirty");
+ ok(!comment1.get('isDirty'), "precond - record should not yet be dirty");
+
+ comment1.deleteRecord();
+
+ ok(post.get('isDirty'), "precond - record should be dirty after change");
+ ok(comment1.get('isDirty'), "precond - record should be dirty after change");
+
+ equal(comment1.get('post'), null, "precond - property reflects changed value");
+ deepEqual(post.get('comments').toArray(), [ comment2 ], "precond - deleted record is removed from parent's hasMany");
+
+ transaction.rollback();
+
+ ok(!post.get('isDirty'), "record should not be dirty after rollback");
+ ok(!comment1.get('isDirty'), "record should not be dirty after rollback");
+
+ equal(comment1.get('post'), post, "property is rolled back to its original value");
+ deepEqual(post.get('comments').toArray(), [ comment1, comment2 ], "property is rolled back to its original value");
+});
+
+test("A deleted record should be restored to a belongsTo relationship if the transaction is rolled back", function() {
+ store.load(Post, { id: 1, title: "My Darkest Node.js Fantasies", comments: [ 1 ] });
+ store.load(Comment, { id: 1, title: "I don't see the appeal of Rails these days when Node.js and Django are both as mature and inherently more scalable than Rails", post: 1 });
+
+ var post = store.find(Post, 1);
+ var comment1 = store.find(Comment, 1);
+
+ var oldValue = comment1.get('post');
+
+ var transaction = store.transaction();
+ transaction.add(post);
+
+ ok(!post.get('isDirty'), "precond - record should not yet be dirty");
+ ok(!comment1.get('isDirty'), "precond - record should not yet be dirty");
+
+ post.deleteRecord();
+
+ ok(post.get('isDirty'), "precond - record should be dirty after change");
+ ok(comment1.get('isDirty'), "precond - record should be dirty after change");
+
+ equal(comment1.get('post'), null, "precond - property reflects changed value");
+ deepEqual(post.get('comments').toArray(), [ ], "precond - deleted record is removed from parent's hasMany");
+
+ transaction.rollback();
+
+ ok(!post.get('isDirty'), "record should not be dirty after rollback");
+ ok(!comment1.get('isDirty'), "record should not be dirty after rollback");
+
+ equal(comment1.get('post'), post, "property is rolled back to its original value");
+ deepEqual(post.get('comments').toArray(), [ comment1 ], "property is rolled back to its original value");
+});
+
+test("A deleted record should be restored to a belongsTo relationship if the transaction is rolled back", function() {
+ store.load(Post, { id: 1, title: "My Darkest Node.js Fantasies", comments: [ 1 ] });
+ store.load(Comment, { id: 1, title: "I don't see the appeal of Rails these days when Node.js and Django are both as mature and inherently more scalable than Rails", post: 1 });
+
+ var post = store.find(Post, 1);
+ var comment1 = store.find(Comment, 1);
+
+ var oldValue = comment1.get('post');
+
+ var transaction = store.transaction();
+ transaction.add(post);
+ transaction.add(comment1);
+
+ ok(!post.get('isDirty'), "precond - record should not yet be dirty");
+ ok(!comment1.get('isDirty'), "precond - record should not yet be dirty");
+
+ post.deleteRecord();
+ comment1.deleteRecord();
+
+ ok(post.get('isDirty'), "precond - record should be dirty after change");
+ ok(comment1.get('isDirty'), "precond - record should be dirty after change");
+
+ equal(comment1.get('post'), null, "precond - property reflects changed value");
+ deepEqual(post.get('comments').toArray(), [ ], "precond - deleted record is removed from parent's hasMany");
+
+ transaction.rollback();
+
+ ok(!post.get('isDirty'), "record should not be dirty after rollback");
+ ok(!comment1.get('isDirty'), "record should not be dirty after rollback");
+
+ equal(comment1.get('post'), post, "property is rolled back to its original value");
+ deepEqual(post.get('comments').toArray(), [ comment1 ], "property is rolled back to its original value");
+});
//test("A deleted record in a transaction with changed attributes should revert to the old attributes when the transaction is rolled back.");
//test("A deleted record in a transaction with a changed belongsTo should revert to the old relationship when the transaction is rolled back.");

0 comments on commit 019ea76

Please sign in to comment.
Something went wrong with that request. Please try again.