Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only remove deleted records form record arrays when saved #3539

Merged
merged 3 commits into from
Jul 18, 2015
Merged
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
19 changes: 0 additions & 19 deletions packages/ember-data/lib/system/model/internal-model.js
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,6 @@ InternalModel.prototype = {
if (this.isDeleted()) {
//TODO: Should probably move this to the state machine somehow
this.becameReady();
this.reconnectRelationships();
}

if (this.isNew()) {
Expand Down Expand Up @@ -449,7 +448,6 @@ InternalModel.prototype = {
this.eachRelationship((name, relationship) => {
if (this._relationships.has(name)) {
var rel = this._relationships.get(name);
//TODO(Igor) figure out whether we want to clear or disconnect
rel.clear();
rel.destroy();
}
Expand All @@ -460,23 +458,6 @@ InternalModel.prototype = {
});
},

disconnectRelationships: function() {
this.eachRelationship((name, relationship) => {
this._relationships.get(name).disconnect();
});
Object.keys(this._implicitRelationships).forEach((key) => {
this._implicitRelationships[key].disconnect();
});
},

reconnectRelationships: function() {
this.eachRelationship((name, relationship) => {
this._relationships.get(name).reconnect();
});
Object.keys(this._implicitRelationships).forEach((key) => this._implicitRelationships[key].reconnect());
},


/**
When a find request is triggered on the store, the user can optionally pass in
attributes and relationships to be preloaded. These are meant to behave as if they
Expand Down
5 changes: 1 addition & 4 deletions packages/ember-data/lib/system/model/states.js
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,6 @@ var DirtyState = {
// EVENTS
deleteRecord: function(internalModel) {
internalModel.transitionTo('deleted.uncommitted');
internalModel.disconnectRelationships();
},

didSetProperty: function(internalModel, context) {
Expand Down Expand Up @@ -410,7 +409,6 @@ var updatedState = dirtyState({
});

createdState.uncommitted.deleteRecord = function(internalModel) {
internalModel.disconnectRelationships();
internalModel.transitionTo('deleted.saved');
internalModel.send('invokeLifecycleCallbacks');
};
Expand All @@ -435,7 +433,6 @@ updatedState.inFlight.unloadRecord = assertAgainstUnloadRecord;

updatedState.uncommitted.deleteRecord = function(internalModel) {
internalModel.transitionTo('deleted.uncommitted');
internalModel.disconnectRelationships();
};

var RootState = {
Expand Down Expand Up @@ -572,7 +569,6 @@ var RootState = {

deleteRecord: function(internalModel) {
internalModel.transitionTo('deleted.uncommitted');
internalModel.disconnectRelationships();
},

unloadRecord: function(internalModel) {
Expand Down Expand Up @@ -685,6 +681,7 @@ var RootState = {
isDirty: false,

setup: function(internalModel) {
internalModel.clearRelationships();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also do this on dematerialize, so it will be called twice now?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I remove the internalModel.clearRelationships(); from the unloadRecord methods?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I would rely on it there, and not here, but I think we can fix that later when I merge the unload refactor

var store = internalModel.store;
store._dematerializeRecord(internalModel);
},
Expand Down
9 changes: 5 additions & 4 deletions packages/ember-data/lib/system/record-array-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,12 @@ export default Ember.Object.extend({
@method updateRecordArrays
*/
updateRecordArrays: function() {
this.changedRecords.forEach((record) => {
if (record.isDeleted()) {
this._recordWasDeleted(record);
this.changedRecords.forEach((internalModel) => {
if (get(internalModel, 'record.isDestroyed') || get(internalModel, 'record.isDestroying') ||
(get(internalModel, 'currentState.stateName') === 'root.deleted.saved')) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

this._recordWasDeleted(internalModel);
} else {
this._recordWasChanged(record);
this._recordWasChanged(internalModel);
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,10 @@ ManyRelationship.prototype.findRecords = function() {
//TODO CLEANUP
return this.store.findMany(this.manyArray.toArray().map((rec) => rec._internalModel)).
then(() => {
//Goes away after the manyArray refactor
this.manyArray.set('isLoaded', true);
if (!this.manyArray.get('isDestroyed')) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems scary, why is this needed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied it from this code https://github.com/bmac/data/blob/rebase-3247/packages/ember-data/lib/system/relationships/state/has-many.js#L187-L189.

I think with the async code its possible to get into a state where the relationship is cleaned up before the findMany resolves.

//Goes away after the manyArray refactor
this.manyArray.set('isLoaded', true);
}
return this.manyArray;
});
};
Expand Down
14 changes: 0 additions & 14 deletions packages/ember-data/lib/system/relationships/state/relationship.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,6 @@ Relationship.prototype = {
}
},

disconnect: function() {
this.members.forEach((member) => this.removeRecordFromInverse(member));
},

reconnect: function() {
this.members.forEach((member) => this.addRecordToInverse(member));
},

removeRecords: function(records) {
records.forEach((record) => this.removeRecord(record));
},
Expand Down Expand Up @@ -138,12 +130,6 @@ Relationship.prototype = {
}
},

addRecordToInverse: function(record) {
if (this.inverseKey) {
record._relationships.get(this.inverseKey).addRecord(this.record);
}
},

removeRecordFromInverse: function(record) {
var inverseRelationship = record._relationships.get(this.inverseKey);
//Need to check for existence, as the record might unloading at the moment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ test("Watching Records", function() {
deepEqual(record.searchKeywords, ['2', 'New Post']);
deepEqual(record.color, 'green');

Ember.run(post, 'deleteRecord');
Ember.run(post, 'unloadRecord');

equal(removedIndex, 1);
equal(removedCount, 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,40 @@ module("integration/deletedRecord - Deleting Records", {
}
});

test("records should not be removed from record arrays just after deleting, but only after commiting them", function () {
var adam, dave;

env.adapter.deleteRecord = function() {
return Ember.RSVP.Promise.resolve();
};

var all;
run(function() {
adam = env.store.push('person', { id: 1, name: "Adam Sunderland" });
dave = env.store.push('person', { id: 2, name: "Dave Sunderland" });
all = env.store.peekAll('person');
});


// pre-condition
equal(all.get('length'), 2, 'pre-condition: 2 records in array');

Ember.run(adam, 'deleteRecord');

equal(all.get('length'), 2, '2 records in array after deleteRecord');

Ember.run(adam, 'save');

equal(all.get('length'), 1, '1 record in array after deleteRecord and save');
});

test("records can be deleted during record array enumeration", function () {
var adam, dave;

env.adapter.deleteRecord = function() {
return Ember.RSVP.Promise.resolve();
};

run(function() {
adam = env.store.push('person', { id: 1, name: "Adam Sunderland" });
dave = env.store.push('person', { id: 2, name: "Dave Sunderland" });
Expand All @@ -35,7 +67,7 @@ test("records can be deleted during record array enumeration", function () {

Ember.run(function() {
all.forEach(function(record) {
record.deleteRecord();
record.destroyRecord();
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1322,7 +1322,7 @@ test("adding and removing records from hasMany relationship #2666", function() {
return comments.get('lastObject').destroyRecord();
}).then(function() {
var comments = post.get('comments');
equal(comments.get('length'), 3, "Comments count after delete");
equal(comments.get('length'), 3, "Comments count after destroy");

// Add another comment #4
var comment = env.store.createRecord('comment');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ module('integration/relationships/many_to_many_test - ManyToMany relationships',
env = setupStore({
user: User,
topic: Topic,
account: Account
account: Account,
adapter: DS.Adapter.extend({
deleteRecord: () => Ember.RSVP.resolve()
})
});

store = env.store;
Expand Down Expand Up @@ -380,89 +383,6 @@ test("Removing a record from a hasMany reflects on the other hasMany side - sync
equal(account.get('users.length'), 0, 'Users were removed correctly');
});

/*
Deleting tests
*/

test("Deleting a record that has a hasMany relationship removes it from the otherMany array but does not remove the other record from itself - async", function () {
var user, topic;
run(function() {
user = store.push({
data: {
id: '1',
type: 'user',
attributes: {
name: 'Stanley'
},
relationships: {
topics: {
data: [{
id: '2',
type: 'topic'
}]
}
}
}
});
topic = store.push({
data: {
id: '2',
type: 'topic',
attributes: {
title: 'EmberFest was great'
}
}
});
});

run(topic, 'deleteRecord');
run(function() {
topic.get('users').then(async(function(fetchedUsers) {
equal(fetchedUsers.get('length'), 1, 'Users are still there');
}));
user.get('topics').then(async(function(fetchedTopics) {
equal(fetchedTopics.get('length'), 0, 'Topic got removed from the user');
equal(fetchedTopics.objectAt(0), null, "Topic can't be fetched");
}));
});
});

test("Deleting a record that has a hasMany relationship removes it from the otherMany array but does not remove the other record from itself - sync", function () {
var account, user;
run(function() {
account = store.push({
data: {
id: '2',
type: 'account',
attributes: {
state: 'lonely'
}
}
});
user = store.push({
data: {
id: '1',
type: 'user',
attributes: {
name: 'Stanley'
},
relationships: {
accounts: {
data: [{
id: '2',
type: 'account'
}]
}
}
}
});
});

run(account, 'deleteRecord');
equal(account.get('users.length'), 1, 'Users are still there');
equal(user.get('accounts.length'), 0, 'Acocount got removed from the user');
});

/*
Rollback Attributes tests
*/
Expand Down
Loading