Skip to content

Commit 8081efb

Browse files
authored
Merge pull request #14 from richmolj/master
When saving, only send dirty attributes
2 parents cb5b9ef + eff16e5 commit 8081efb

File tree

6 files changed

+72
-4
lines changed

6 files changed

+72
-4
lines changed

src/model.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,11 @@ export default class Model {
256256
return dc.check(relationships);
257257
}
258258

259+
changes() : Object {
260+
let dc = new DirtyChecker(this);
261+
return dc.dirtyAttributes();
262+
}
263+
259264
hasDirtyRelation(relationName: string, relatedModel: Model) : boolean {
260265
let dc = new DirtyChecker(this);
261266
return dc.checkRelation(relationName, relatedModel);

src/util/dirty-check.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,23 @@ class DirtyChecker {
4141
this._isUnpersisted()
4242
}
4343

44+
dirtyAttributes() : Object {
45+
let dirty = {};
46+
47+
for (let key of Object.keys(this.model.attributes)) {
48+
let prior = this.model._originalAttributes[key];
49+
let current = this.model.attributes[key];
50+
51+
if (!this.model.isPersisted()) {
52+
dirty[key] = [null, current];
53+
} else if (prior != current) {
54+
dirty[key] = [prior, current]
55+
}
56+
}
57+
58+
return dirty;
59+
}
60+
4461
// TODO: allow attributes == {} configurable
4562
private _isUnpersisted() {
4663
return !this.model.isPersisted() && JSON.stringify(this.model.attributes) !== JSON.stringify({});

src/util/write-payload.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ export default class WritePayload {
2121

2222
this._eachAttribute((key, value) => {
2323
let snakeKey = snakeCase(key);
24-
attrs[snakeKey] = value;
24+
25+
if (!this.model.isPersisted() || this.model.changes()[key]) {
26+
attrs[snakeKey] = value;
27+
}
2528
});
2629

2730
return attrs;

test/integration/nested-persistence-test.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ let expectedUpdatePayload = function(method) {
7777
data: {
7878
id: '1',
7979
type: 'authors',
80-
attributes: { first_name: 'Stephen' },
8180
relationships: {
8281
books: {
8382
data: [
@@ -206,7 +205,6 @@ describe('nested persistence', function() {
206205
// todo test on the way back - id set, attrs updated, isPersisted
207206
// todo remove #destroy? and just save when markwithpersisted? combo? for ombined payload
208207
// todo test unique includes/circular relationshio
209-
// todo only send dirty
210208
it('sends the correct payload', function(done) {
211209
instance.save({ with: { books: 'genre' } }).then((response) => {
212210
expect(payloads[0]).to.deep.equal(expectedCreatePayload);

test/integration/persistence-test.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ describe('Model persistence', function() {
5151
});
5252

5353
describe('#save()', function() {
54-
describe('when a unpersisted attr', function() {
54+
describe('when an unpersisted attr', function() {
5555
it('does not send the attr to server', function(done) {
5656
instance = new PersonWithExtraAttr({ extraThing: 'foo' });
5757
expect(instance.extraThing).to.eq('foo');
@@ -92,6 +92,26 @@ describe('Model persistence', function() {
9292
expect(instance.isPersisted()).to.eq(true);
9393
});
9494
});
95+
96+
describe('when no dirty attributes', function() {
97+
beforeEach(function() {
98+
instance.firstName = 'Joe';
99+
instance.isPersisted(true);
100+
});
101+
102+
it('does not send attributes to the server', function(done) {
103+
instance.save().then(() => {
104+
console.log(putPayloads[0])
105+
expect(putPayloads[0]).to.deep.equal({
106+
data: {
107+
id: '1',
108+
type: 'people'
109+
}
110+
});
111+
done();
112+
});
113+
});
114+
})
95115
});
96116

97117
describe('when the model is not already persisted', function() {

test/unit/model-test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,31 @@ describe('Model', function() {
617617
});
618618
});
619619

620+
describe('changes', function() {
621+
describe('when unpersisted', function() {
622+
it('counts everything but nulls', function() {
623+
instance = new Author({ firstName: 'foo' });
624+
expect(instance.changes()).to.deep.equal({
625+
firstName: [null, 'foo']
626+
});
627+
});
628+
});
629+
630+
describe('when persisted', function() {
631+
it('only counts dirty attrs', function() {
632+
instance = new Author({ firstName: 'foo' });
633+
instance.isPersisted(true);
634+
expect(instance.changes()).to.deep.equal({});
635+
instance.firstName = 'bar'
636+
expect(instance.changes()).to.deep.equal({
637+
firstName: ['foo', 'bar']
638+
});
639+
instance.isPersisted(true);
640+
expect(instance.changes()).to.deep.equal({});
641+
});
642+
});
643+
});
644+
620645
describe('isDirty', function() {
621646
describe('when an attribute changes', function() {
622647
it('is marked as dirty', function() {

0 commit comments

Comments
 (0)