Skip to content

Commit

Permalink
Implement dirty tracking and rollback of belongsTo relationships.
Browse files Browse the repository at this point in the history
  • Loading branch information
arenoir committed Aug 25, 2015
1 parent 5251766 commit a7454a4
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 1 deletion.
13 changes: 12 additions & 1 deletion packages/ember-data/lib/system/model/internal-model.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ InternalModel.prototype = {
isEmpty: retrieveFromCurrentState('isEmpty'),
isLoading: retrieveFromCurrentState('isLoading'),
isLoaded: retrieveFromCurrentState('isLoaded'),
hasDirtyAttributes: retrieveFromCurrentState('hasDirtyAttributes'),
isSaving: retrieveFromCurrentState('isSaving'),
isDeleted: retrieveFromCurrentState('isDeleted'),
isNew: retrieveFromCurrentState('isNew'),
Expand Down Expand Up @@ -327,6 +326,12 @@ InternalModel.prototype = {
}
},

rollback: function() {
this.rollbackAttributes();
this.rollbackRelationships();
this.send('rolledBack');
},

rollbackAttributes: function() {
var dirtyKeys = Object.keys(this._attributes);

Expand Down Expand Up @@ -462,6 +467,12 @@ InternalModel.prototype = {
});
},

rollbackRelationships: function() {
this.eachRelationship((name, relationship) => {
this._relationships.get(name).rollback();
});
},

/**
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
16 changes: 16 additions & 0 deletions packages/ember-data/lib/system/model/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ var Model = Ember.Object.extend(Ember.Evented, {
hasDirtyAttributes: Ember.computed('currentState.isDirty', function() {
return this.get('currentState.isDirty');
}),

hasDirtyRelationships: function() {
return this._internalModel._relationships.isDirty();
},

/**
If this property is `true` the record is in the `saving` state. A
record enters the saving state when `save` is called, but the
Expand Down Expand Up @@ -629,6 +634,11 @@ var Model = Ember.Object.extend(Ember.Evented, {
return diffData;
},


rollback: function() {
this._internalModel.rollback();
},

//TODO discuss with tomhuda about events/hooks
//Bring back as hooks?
/**
Expand Down Expand Up @@ -667,6 +677,12 @@ var Model = Ember.Object.extend(Ember.Evented, {
this._internalModel.rollbackAttributes();
},


rollbackRelationships: function() {
this._internalModel.rollbackRelationships();
},


/*
@method _createSnapshot
@private
Expand Down
1 change: 1 addition & 0 deletions packages/ember-data/lib/system/model/states.js
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ var DirtyState = {

rollback: function(internalModel) {
internalModel.rollbackAttributes();
internalModel.rollbackRelationships();
internalModel.triggerLater('ready');
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ BelongsToRelationship.prototype.addRecord = function(newRecord) {

this.inverseRecord = newRecord;
this._super$addRecord(newRecord);

this.isDirty = this.canonicalState !== newRecord;
this.record.notifyBelongsToChanged(this.key);
};

Expand Down Expand Up @@ -138,3 +140,7 @@ BelongsToRelationship.prototype.getRecord = function() {
return toReturn;
}
};

BelongsToRelationship.prototype.rollback = function() {
this.setRecord(this.canonicalState);
};
10 changes: 10 additions & 0 deletions packages/ember-data/lib/system/relationships/state/create.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,13 @@ Relationships.prototype.get = function(key) {
}
return relationships[key];
};


Relationships.prototype.isDirty = function() {
var relationshipsByName = get(this.record.type, 'relationshipsByName');
var keys = relationshipsByName._keys.toArray();

return keys.some((key) => {
return this.get(key).isDirty;
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export default function Relationship(store, record, inverseKey, relationshipMeta
this.linkPromise = null;
this.meta = null;
this.hasData = false;
this.isDirty = false;
}

Relationship.prototype = {
Expand Down Expand Up @@ -216,5 +217,9 @@ Relationship.prototype = {

setHasData: function(value) {
this.hasData = value;
},

rollback: function() {

}
};
Original file line number Diff line number Diff line change
Expand Up @@ -984,3 +984,63 @@ test("Model's belongsTo relationship should be created during 'get' method", fun
ok(user._internalModel._relationships.has('favouriteMessage'), "Newly created record with relationships in params passed in its constructor should have relationships");
});
});


//
test("relationship assignment is tracked", function () {
var book, author, anotherAuthor;

run(function() {
book = env.store.push({
data: {
id: '1',
type: 'book',
attributes: {
name: "A book with one true author?"
},
relationships: {
author: {
data: {
id: '2',
type: 'author'
}
}
}
}
});
author = env.store.push({
data: {
id: '2',
type: 'author',
attributes: {
name: 'Stanley'
}
}
});

anotherAuthor = env.store.push({
data: {
id: '3',
type: 'author',
attributes: {
name: 'Aaron'
}
}
});
});


run(function() {
equal(book.hasDirtyRelationships(), false, "Book should not have dirty relationships on load");

book.set('author', anotherAuthor);
equal(book.hasDirtyRelationships(), true, "Book has dirty relationships when new author is assigned");

equal(book.get('author'), anotherAuthor, "Book has another author assigned");

book.rollback();
equal(book.hasDirtyRelationships(), false, "Book does not have dirty relationships when new author assignment is rolled back");
equal(book.get('author'), author, "Book rolls back author");
});
});

0 comments on commit a7454a4

Please sign in to comment.