Permalink
Browse files

Add hook for preserving dirty children on load

This is specifically needed for the REST adapter to ensure that dirty
children are preserved when new parent data comes back from the server.
Because the children are responsible for saving the relationship, the
parent record on the server won't yet know about the children. If the
children are dirty, it means they will be persisted to the server on
their transaction's next commit, at which point the server will then
know about them.
  • Loading branch information...
1 parent e5f89de commit d579d1472bdd88bfec095dc10e8008546f1bb6cf Ian Lesperance & Robert Gallagher committed with elliterate Dec 4, 2012
@@ -98,6 +98,10 @@ DS.RESTAdapter = DS.Adapter.extend({
}, this);
},
+ shouldPreserveDirtyRecords: function(relationship) {
+ return relationship.kind === 'hasMany';
+ },
+
dirtyRecordsForRecordChange: function(dirtySet, record) {
this._dirtyTree(dirtySet, record);
},
@@ -462,6 +462,19 @@ DS.Adapter = Ember.Object.extend(DS._Mappable, {
/**
@private
+ Determines whether dirty records for a particular association
+ should be preserved in the face of re-materialization.
+
+ @param {Object} association the association meta information
+ @return {Boolean}
+ */
+ shouldPreserveDirtyRecords: function(association) {
+ return false;
+ },
+
+ /**
+ @private
+
This method recursively climbs the superclass hierarchy and
registers any class-registered transforms on the adapter's
serializer.
@@ -185,19 +185,30 @@ DS.Model = Ember.Object.extend(Ember.Evented, LoadPromise, {
}, 'data'),
hasManyDidChange: function(key) {
- var cachedValue = this.cacheFor(key);
+ var cachedValue = this.cacheFor(key),
+ store = get(this, 'store'),
+ adapter = store.adapterForType(this.constructor);
if (cachedValue) {
- var type = get(this.constructor, 'relationshipsByName').get(key).type;
- var store = get(this, 'store');
- var ids = this._data.hasMany[key] || [];
+ var relationship = get(this.constructor, 'relationshipsByName').get(key),
+ type = relationship.type,
+ ids = this._data.hasMany[key] || [],
+ dirtyReferences;
var references = map(ids, function(id) {
// if it was already a reference, return the reference
if (typeof id === 'object') { return id; }
return store.referenceForId(type, id);
});
+ if (adapter.shouldPreserveDirtyRecords(relationship)) {
+ dirtyReferences = get(cachedValue, 'content').map(function(reference) {
+ var record = store.findByClientId(reference.type, reference.clientId);
+ return get(record, 'isDirty') ? reference : null;
+ });
+ references = references.concat(Ember.A(dirtyReferences).compact());
+ }
+
set(cachedValue, 'content', Ember.A(references));
}
},
@@ -100,6 +100,9 @@ test("creating a parent and child in the same commit", function() {
expectState(comment, 'saving', true);
expectStates([person, comment], 'error', false);
+ deepEqual(person.get('comments').toArray(), [ comment ], "The person has the comment");
+ equal(comment.get('person'), person, "The comment belongs to the person");
+
equal(requests.length, 2, "A second request is attempted");
equal(requests[1].url, "/comments", "The comment is created second");
equal(requests[1].data.comment.person_id, 1, "The submitted comment attributes include the person_id");
@@ -115,6 +118,9 @@ test("creating a parent and child in the same commit", function() {
expectStates([person, comment], 'saving', false);
expectStates([person, comment], 'error', false);
+
+ deepEqual(person.get('comments').toArray(), [ comment ], "The person has the comment");
+ equal(comment.get('person'), person, "The comment belongs to the person");
});
});
@@ -148,6 +154,9 @@ test("creating a parent and updating a child in the same commit", function() {
expectState(comment, 'saving', true);
expectStates([person, comment], 'error', false);
+ deepEqual(person.get('comments').toArray(), [ comment ], "The person has the comment");
+ equal(comment.get('person'), person, "The comment belongs to the person");
+
equal(requests.length, 2, "A second request is attempted");
equal(requests[1].url, "/comments/2", "The comment is updated second");
equal(requests[1].data.comment.person_id, 1, "The submitted comment attributes include the person_id");
@@ -161,5 +170,8 @@ test("creating a parent and updating a child in the same commit", function() {
expectStates([person, comment], 'saving', false);
expectStates([person, comment], 'error', false);
+
+ deepEqual(person.get('comments').toArray(), [ comment ], "The person has the comment");
+ equal(comment.get('person'), person, "The comment belongs to the person");
});
});

0 comments on commit d579d14

Please sign in to comment.