Skip to content

Commit

Permalink
[FEATURE ds-rollback-attribute] Add rolling back of a single model at…
Browse files Browse the repository at this point in the history
…tribute
  • Loading branch information
courajs committed Mar 18, 2016
1 parent 3e32efe commit c5a8a0b
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 1 deletion.
14 changes: 14 additions & 0 deletions addon/-private/system/model/internal-model.js
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ InternalModel.prototype = {
this.record._notifyProperties(dirtyKeys);

},

/*
@method transitionTo
@private
Expand Down Expand Up @@ -855,3 +856,16 @@ if (isEnabled('ds-references')) {
};

}

if (isEnabled('ds-rollback-attribute')) {
InternalModel.prototype.rollbackAttribute = function rollbackAttribute(attributeName) {
var attrs = this._attributes;
var dirtyKeys = Object.keys(attrs);
if (dirtyKeys.indexOf(attributeName) !== -1) {
delete this._attributes[attributeName];
this.send('propertyWasReset', attributeName);
this.record.notifyPropertyChange(attributeName);
}
}
}

24 changes: 24 additions & 0 deletions addon/-private/system/model/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,30 @@ if (isEnabled("ds-references")) {

}

if (isEnabled('ds-rollback-attribute')) {
Model.reopen({
/**
Discards any unsaved changes to the given attribute.
Example
```javascript
record.get('name'); // 'Untitled Document'
record.set('name', 'Doc 1');
record.get('name'); // 'Doc 1'
record.rollbackAttribute('name');
record.get('name'); // 'Untitled Document'
```
@method rollbackAttribute
*/
rollbackAttribute(attributeName) {
this._internalModel.rollbackAttribute(attributeName);
}
});
}


Model.reopenClass(RelationshipsClassMethodsMixin);
Model.reopenClass(AttrClassMethodsMixin);

Expand Down
3 changes: 2 additions & 1 deletion config/features.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
"ds-references": null,
"ds-transform-pass-options": null,
"ds-pushpayload-return": null,
"ds-serialize-ids-and-types": null
"ds-serialize-ids-and-types": null,
"ds-rollback-attribute": null
}
59 changes: 59 additions & 0 deletions tests/unit/model-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,65 @@ test("changedAttributes() works while the record is being updated", function(ass
});
});

if (isEnabled('ds-rollback-attribute')) {
test("rollbackAttribute() reverts a single attribute to its canonical value", function(assert) {
assert.expect(5);
env.adapter.shouldBackgroundReloadRecord = () => false;

run(function() {
store.push({
data: {
type: 'person',
id: '1',
attributes: {
name: 'Peter',
isDrugAddict: true
}
}
});

store.findRecord('person', 1).then(function(person) {
assert.equal(person.get('hasDirtyAttributes'), false, "precond - person record should not be dirty");
person.setProperties({
name: 'Piper',
isDrugAddict: false
});
assert.equal(person.get('hasDirtyAttributes'), true, "record becomes dirty after setting property to a new value");
person.rollbackAttribute('isDrugAddict');
assert.equal(person.get('isDrugAddict'), true, "The specified attribute is rolled back");
assert.equal(person.get('name'), 'Piper', "Unspecified attributes are not rolled back");
assert.equal(person.get('hasDirtyAttributes'), true, "record with changed attributes is still dirty");
});
});
});

test("Rolling back the final value with rollbackAttribute() causes it to become clean again", function(assert) {
assert.expect(3);
env.adapter.shouldBackgroundReloadRecord = () => false;

run(function() {
store.push({
data: {
type: 'person',
id: '1',
attributes: {
name: 'Peter',
isDrugAddict: true
}
}
});

store.findRecord('person', 1).then(function(person) {
assert.equal(person.get('hasDirtyAttributes'), false, "precond - person record should not be dirty");
person.set('isDrugAddict', false);
assert.equal(person.get('hasDirtyAttributes'), true, "record becomes dirty after setting property to a new value");
person.rollbackAttribute('isDrugAddict');
assert.equal(person.get('hasDirtyAttributes'), false, "record becomes clean after resetting property to the old value");
});
});
});
}

test("a DS.Model does not require an attribute type", function(assert) {
var Tag = DS.Model.extend({
name: DS.attr()
Expand Down

0 comments on commit c5a8a0b

Please sign in to comment.