Skip to content

Commit f887366

Browse files
committed
Merge branc 'master' of github.com:danielspaniel/ember-data-change-tracker
2 parents d267c02 + 3b8197e commit f887366

File tree

8 files changed

+214
-72
lines changed

8 files changed

+214
-72
lines changed

addon/model-ext.js

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@ import Tracker from './tracker';
44

55
Model.reopen({
66

7+
init(){
8+
this._super(...arguments);
9+
if (Tracker.isAutoSaveEnabled(this)) {
10+
this.initTracking();
11+
}
12+
if (Tracker.isIsDirtyEnabled(this)) {
13+
// this is experimental
14+
Tracker.initializeDirtiness(this);
15+
}
16+
17+
this.setupTrackerMetaData();
18+
this.setupUnknownRelationshipLoadObservers();
19+
},
20+
721
/**
822
* Did an attribute/association change?
923
*
@@ -60,9 +74,43 @@ Model.reopen({
6074

6175
// alias for saveChanges method
6276
startTrack() {
77+
this.initTracking();
6378
this.saveChanges();
6479
},
6580

81+
// Ember Data DS.Model events
82+
// http://api.emberjs.com/ember-data/3.10/classes/DS.Model/events
83+
//
84+
// Replaces deprecated Ember.Evented usage:
85+
// https://github.com/emberjs/rfcs/blob/master/text/0329-deprecated-ember-evented-in-ember-data.md
86+
// Related: https://github.com/emberjs/rfcs/pull/329
87+
88+
initTracking(){
89+
90+
this.didCreate = () => {
91+
this._super(...arguments);
92+
this.saveOnCreate();
93+
}
94+
95+
this.didUpdate = () => {
96+
this._super(...arguments);
97+
this.saveOnUpdate();
98+
}
99+
100+
this.didDelete = () => {
101+
this._super(...arguments);
102+
this.clearSavedAttributes();
103+
}
104+
105+
this.ready = () => {
106+
this._super(...arguments);
107+
this.setupTrackerMetaData();
108+
this.setupUnknownRelationshipLoadObservers();
109+
},
110+
111+
Tracker.setupTracking(this);
112+
},
113+
66114
/**
67115
* Save the current state of the model
68116
*
@@ -148,33 +196,5 @@ Model.reopen({
148196
this.removeObserver(key, this, 'observeUnknownRelationshipLoaded');
149197
}
150198
}
151-
},
152-
153-
// Ember Data DS.Model events
154-
// http://api.emberjs.com/ember-data/3.10/classes/DS.Model/events
155-
//
156-
// Replaces deprecated Ember.Evented usage:
157-
// https://github.com/emberjs/rfcs/blob/master/text/0329-deprecated-ember-evented-in-ember-data.md
158-
// Related: https://github.com/emberjs/rfcs/pull/329
159-
160-
ready() {
161-
this._super(...arguments);
162-
this.setupTrackerMetaData();
163-
this.setupUnknownRelationshipLoadObservers();
164-
},
165-
166-
didCreate() {
167-
this._super(...arguments);
168-
this.saveOnCreate();
169-
},
170-
171-
didUpdate() {
172-
this._super(...arguments);
173-
this.saveOnUpdate();
174-
},
175-
176-
didDelete() {
177-
this._super(...arguments);
178-
this.clearSavedAttributes();
179-
},
199+
}
180200
});
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import Model from 'ember-data/model';
2+
import attr from 'ember-data/attr';
3+
4+
export default Model.extend({
5+
changeTracker: {trackHasMany: true, auto: true, enableIsDirty: true},
6+
7+
name: attr('string'),
8+
propA: attr('string'),
9+
propB: attr('string'),
10+
propC: attr('string'),
11+
propD: attr('string'),
12+
propE: attr('string'),
13+
propF: attr('string'),
14+
propG: attr('string'),
15+
propH: attr('string'),
16+
propI: attr('string'),
17+
propJ: attr('string'),
18+
propK: attr('string'),
19+
propL: attr('string'),
20+
propM: attr('string'),
21+
propN: attr('string'),
22+
propO: attr('string'),
23+
propP: attr('string'),
24+
propQ: attr('string'),
25+
propR: attr('string'),
26+
propS: attr('string'),
27+
propT: attr('string'),
28+
propU: attr('string'),
29+
propV: attr('string'),
30+
propW: attr('string'),
31+
propX: attr('string'),
32+
propY: attr('string'),
33+
propZ: attr('string')
34+
});
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import Model from 'ember-data/model';
2+
import attr from 'ember-data/attr';
3+
4+
export default Model.extend({
5+
changeTracker: {trackHasMany: false, auto: false, enableIsDirty: false},
6+
7+
name: attr('string'),
8+
propA: attr('string'),
9+
propB: attr('string'),
10+
propC: attr('string'),
11+
propD: attr('string'),
12+
propE: attr('string'),
13+
propF: attr('string'),
14+
propG: attr('string'),
15+
propH: attr('string'),
16+
propI: attr('string'),
17+
propJ: attr('string'),
18+
propK: attr('string'),
19+
propL: attr('string'),
20+
propM: attr('string'),
21+
propN: attr('string'),
22+
propO: attr('string'),
23+
propP: attr('string'),
24+
propQ: attr('string'),
25+
propR: attr('string'),
26+
propS: attr('string'),
27+
propT: attr('string'),
28+
propU: attr('string'),
29+
propV: attr('string'),
30+
propW: attr('string'),
31+
propX: attr('string'),
32+
propY: attr('string'),
33+
propZ: attr('string')
34+
});

tests/dummy/app/models/project.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,9 @@ export default Model.extend({
77
title: attr('string'),
88
blob: attr(),
99
company: belongsTo('company', { async: true }),
10-
details: hasMany('detail')
10+
details: hasMany('detail'),
11+
12+
init(){
13+
this._super(...arguments);
14+
}
1115
});
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import FactoryGuy from 'ember-data-factory-guy';
2+
3+
const randomString = () => Math.random().toString(36).substring(2, 11) + Math.random().toString(36).substring(2, 15);
4+
5+
export const defaultTraits = {
6+
style: 'normal',
7+
name: (f)=>`User${f.id}`,
8+
propA: randomString,
9+
propB: randomString,
10+
propC: randomString,
11+
propD: randomString,
12+
propE: randomString,
13+
propF: randomString,
14+
propG: randomString,
15+
propH: randomString,
16+
propI: randomString,
17+
propJ: randomString,
18+
propK: randomString,
19+
propL: randomString,
20+
propM: randomString,
21+
propN: randomString,
22+
propO: randomString,
23+
propP: randomString,
24+
propQ: randomString,
25+
propR: randomString,
26+
propS: randomString,
27+
propT: randomString,
28+
propU: randomString,
29+
propV: randomString,
30+
propW: randomString,
31+
propX: randomString,
32+
propY: randomString,
33+
propZ: randomString
34+
}
35+
36+
FactoryGuy.define('perf-model-tracked', {
37+
default: defaultTraits,
38+
});
39+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import FactoryGuy from 'ember-data-factory-guy';
2+
import { defaultTraits } from './perf-model-tracked';
3+
4+
FactoryGuy.define('perf-model-untracked', {
5+
6+
default: defaultTraits
7+
});
8+

tests/unit/tracker-test.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,38 @@ module('Unit | Tracker', function(hooks) {
157157
});
158158
});
159159

160+
module('Unit | performance', function(hooks){
161+
setupTest(hooks);
162+
163+
hooks.beforeEach(function() {
164+
manualSetup(this);
165+
});
166+
167+
const instanceCount = 200;
168+
const iterations = 10;
169+
170+
// This approach has limitations. Real world use cases are exponentially slower, however this is of use for baselines.
171+
test('performance check', function(assert) {
172+
const untrackedTimes = [],
173+
trackedTimes = [];
174+
175+
for (let i = 0; i < iterations; i++) {
176+
let t1 = performance.now();
177+
makeList('perf-model-untracked', instanceCount);
178+
let t2 = performance.now();
179+
makeList('perf-model-tracked', instanceCount);
180+
let t3 = performance.now();
181+
182+
untrackedTimes.push(Math.round(t2-t1))
183+
trackedTimes.push(Math.round(t3-t2))
184+
}
185+
const sum = arr => arr.reduce((a,b) => a+b , 0)
186+
187+
assert.ok(true, `Average Untracked ${iterations} @ ${instanceCount} :: ${sum(untrackedTimes)/untrackedTimes.length} per iteration`)
188+
assert.ok(true, `Average Tracked ${iterations} @ ${instanceCount} :: ${sum(trackedTimes)/trackedTimes.length} per iteration`)
189+
});
190+
})
191+
160192
module('Unit | previously unloaded model test', function(hooks) {
161193
setupTest(hooks);
162194

yarn.lock

Lines changed: 13 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,19 +1494,12 @@ async-promise-queue@^1.0.3:
14941494
async "^2.4.1"
14951495
debug "^2.6.8"
14961496

1497-
async@^1.4.0, async@^1.5.2:
1497+
async@^1.5.2:
14981498
version "1.5.2"
14991499
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
15001500
integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=
15011501

15021502
async@^2.4.1:
1503-
version "2.5.0"
1504-
resolved "https://registry.yarnpkg.com/async/-/async-2.5.0.tgz#843190fd6b7357a0b9e1c956edddd5ec8462b54d"
1505-
integrity sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==
1506-
dependencies:
1507-
lodash "^4.14.0"
1508-
1509-
async@^2.5.0:
15101503
version "2.6.1"
15111504
resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610"
15121505
integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==
@@ -3712,10 +3705,10 @@ commander@^2.6.0:
37123705
resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563"
37133706
integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==
37143707

3715-
commander@~2.17.1:
3716-
version "2.17.1"
3717-
resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
3718-
integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==
3708+
commander@~2.20.3:
3709+
version "2.20.3"
3710+
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
3711+
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
37193712

37203713
common-tags@^1.4.0:
37213714
version "1.7.2"
@@ -6302,29 +6295,7 @@ growly@^1.3.0:
63026295
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
63036296
integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=
63046297

6305-
handlebars@^4.0.11:
6306-
version "4.0.12"
6307-
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.12.tgz#2c15c8a96d46da5e266700518ba8cb8d919d5bc5"
6308-
integrity sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==
6309-
dependencies:
6310-
async "^2.5.0"
6311-
optimist "^0.6.1"
6312-
source-map "^0.6.1"
6313-
optionalDependencies:
6314-
uglify-js "^3.1.4"
6315-
6316-
handlebars@^4.0.4:
6317-
version "4.0.10"
6318-
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.10.tgz#3d30c718b09a3d96f23ea4cc1f403c4d3ba9ff4f"
6319-
integrity sha1-PTDHGLCaPZbyPqTMH0A8TTup/08=
6320-
dependencies:
6321-
async "^1.4.0"
6322-
optimist "^0.6.1"
6323-
source-map "^0.4.4"
6324-
optionalDependencies:
6325-
uglify-js "^2.6"
6326-
6327-
handlebars@~4.1.2:
6298+
handlebars@^4.0.11, handlebars@^4.0.4, handlebars@~4.1.2:
63286299
version "4.1.2"
63296300
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.2.tgz#b6b37c1ced0306b221e094fc7aca3ec23b131b67"
63306301
integrity sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==
@@ -7835,7 +7806,7 @@ lodash@^3.10.1:
78357806
resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
78367807
integrity sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=
78377808

7838-
lodash@^4.14.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.4, lodash@^4.3.0, lodash@^4.6.1:
7809+
lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.4, lodash@^4.3.0, lodash@^4.6.1:
78397810
version "4.17.15"
78407811
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
78417812
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
@@ -10331,7 +10302,7 @@ source-map-url@^0.4.0:
1033110302
resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
1033210303
integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=
1033310304

10334-
[email protected], source-map@^0.4.2, source-map@^0.4.4:
10305+
[email protected], source-map@^0.4.2:
1033510306
version "0.4.4"
1033610307
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b"
1033710308
integrity sha1-66T12pwNyZneaAMti092FzZSA2s=
@@ -10999,7 +10970,7 @@ uc.micro@^1.0.5:
1099910970
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.5.tgz#0c65f15f815aa08b560a61ce8b4db7ffc3f45376"
1100010971
integrity sha512-JoLI4g5zv5qNyT09f4YAvEZIIV1oOjqnewYg5D38dkQljIzpPT296dbIGvKro3digYI1bkb7W6EP1y4uDlmzLg==
1100110972

11002-
uglify-js@^2.6, uglify-js@^2.7.0:
10973+
uglify-js@^2.7.0:
1100310974
version "2.8.29"
1100410975
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
1100510976
integrity sha1-KcVzMUgFe7Th913zW3qcty5qWd0=
@@ -11010,11 +10981,11 @@ uglify-js@^2.6, uglify-js@^2.7.0:
1101010981
uglify-to-browserify "~1.0.0"
1101110982

1101210983
uglify-js@^3.1.4:
11013-
version "3.4.9"
11014-
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3"
11015-
integrity sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==
10984+
version "3.7.3"
10985+
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.3.tgz#f918fce9182f466d5140f24bb0ff35c2d32dcc6a"
10986+
integrity sha512-7tINm46/3puUA4hCkKYo4Xdts+JDaVC9ZPRcG8Xw9R4nhO/gZgUM3TENq8IF4Vatk8qCig4MzP/c8G4u2BkVQg==
1101610987
dependencies:
11017-
commander "~2.17.1"
10988+
commander "~2.20.3"
1101810989
source-map "~0.6.1"
1101910990

1102010991
uglify-to-browserify@~1.0.0:

0 commit comments

Comments
 (0)