epf-source 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/dist/epf.js +284 -145
- data/dist/epf.js.map +1 -0
- data/lib/epf/source.rb +4 -0
- metadata +3 -2
data/dist/epf.js
CHANGED
@@ -34,7 +34,7 @@
|
|
34
34
|
var cwd = '/';
|
35
35
|
return {
|
36
36
|
title: 'browser',
|
37
|
-
version: 'v0.
|
37
|
+
version: 'v0.10.13',
|
38
38
|
browser: true,
|
39
39
|
env: {},
|
40
40
|
argv: [],
|
@@ -55,7 +55,6 @@
|
|
55
55
|
require('/lib/model/index.js', module);
|
56
56
|
require('/lib/session/index.js', module);
|
57
57
|
require('/lib/serializer/index.js', module);
|
58
|
-
require('/lib/session/index.js', module);
|
59
58
|
require('/lib/local/index.js', module);
|
60
59
|
require('/lib/rest/index.js', module);
|
61
60
|
});
|
@@ -166,6 +165,22 @@
|
|
166
165
|
return null;
|
167
166
|
}
|
168
167
|
},
|
168
|
+
extractRevision: function (type, hash) {
|
169
|
+
var revision = this._revision(type);
|
170
|
+
if (hash.hasOwnProperty(revision) && hash[revision] !== null) {
|
171
|
+
return parseInt(hash[revision]);
|
172
|
+
} else {
|
173
|
+
return undefined;
|
174
|
+
}
|
175
|
+
},
|
176
|
+
extractClientRevision: function (type, hash) {
|
177
|
+
var revision = this._clientRevision(type);
|
178
|
+
if (hash.hasOwnProperty(revision) && hash[revision] !== null) {
|
179
|
+
return parseInt(hash[revision]);
|
180
|
+
} else {
|
181
|
+
return undefined;
|
182
|
+
}
|
183
|
+
},
|
169
184
|
extractHasMany: function (type, hash, key) {
|
170
185
|
return hash[key];
|
171
186
|
},
|
@@ -442,6 +457,8 @@
|
|
442
457
|
deserialize: mustImplement('deserialize'),
|
443
458
|
extractId: mustImplement('extractId'),
|
444
459
|
extractClientId: mustImplement('extractClientId'),
|
460
|
+
extractRevision: mustImplement('extractRevision'),
|
461
|
+
extractClientRevision: mustImplement('extractClientRevision'),
|
445
462
|
extractAttribute: mustImplement('extractAttribute'),
|
446
463
|
extractHasMany: mustImplement('extractHasMany'),
|
447
464
|
extractBelongsTo: mustImplement('extractBelongsTo'),
|
@@ -449,6 +466,8 @@
|
|
449
466
|
var model = this.createModel(type);
|
450
467
|
set(model, 'id', this.extractId(type, hash));
|
451
468
|
set(model, 'clientId', this.extractClientId(type, hash));
|
469
|
+
set(model, 'rev', this.extractRevision(type, hash));
|
470
|
+
set(model, 'clientRev', this.extractClientRevision(type, hash));
|
452
471
|
this.deserializeAttributes(model, hash);
|
453
472
|
this.deserializeRelationships(model, hash);
|
454
473
|
return model;
|
@@ -573,12 +592,18 @@
|
|
573
592
|
},
|
574
593
|
serialize: function (record, options) {
|
575
594
|
options = options || {};
|
576
|
-
var serialized = this.createSerializedForm(), id;
|
595
|
+
var serialized = this.createSerializedForm(), id, rev, clientRev;
|
577
596
|
if (options.includeId) {
|
578
597
|
if (id = get(record, 'id')) {
|
579
598
|
this._addId(serialized, record.constructor, id);
|
580
599
|
}
|
581
600
|
this._addClientId(serialized, record.constructor, get(record, 'clientId'));
|
601
|
+
if (rev = get(record, 'rev')) {
|
602
|
+
this._addRevision(serialized, record.constructor, get(record, 'rev'));
|
603
|
+
}
|
604
|
+
if (clientRev = get(record, 'clientRev')) {
|
605
|
+
this._addClientRevision(serialized, record.constructor, get(record, 'clientRev'));
|
606
|
+
}
|
582
607
|
}
|
583
608
|
if (options.includeType) {
|
584
609
|
this.addType(serialized, record.constructor);
|
@@ -601,6 +626,12 @@
|
|
601
626
|
serializeClientId: function (clientId) {
|
602
627
|
return clientId;
|
603
628
|
},
|
629
|
+
serializeRevision: function (rev) {
|
630
|
+
return rev;
|
631
|
+
},
|
632
|
+
serializeClientRevision: function (rev) {
|
633
|
+
return rev;
|
634
|
+
},
|
604
635
|
addAttributes: function (data, record) {
|
605
636
|
record.eachAttribute(function (name, attribute) {
|
606
637
|
this._addAttribute(data, record, name, attribute.type);
|
@@ -632,6 +663,12 @@
|
|
632
663
|
clientKey: function (type) {
|
633
664
|
return 'client_id';
|
634
665
|
},
|
666
|
+
revision: function (type) {
|
667
|
+
return 'rev';
|
668
|
+
},
|
669
|
+
clientRevision: function (type) {
|
670
|
+
return 'client_rev';
|
671
|
+
},
|
635
672
|
keyForBelongsTo: function (type, name) {
|
636
673
|
return this.keyForAttributeName(type, name);
|
637
674
|
},
|
@@ -654,6 +691,22 @@
|
|
654
691
|
return this.clientKey(type);
|
655
692
|
}
|
656
693
|
},
|
694
|
+
_revision: function (type) {
|
695
|
+
var config = this.configurationForType(type), revision = config && config.revision;
|
696
|
+
if (revision) {
|
697
|
+
return revision;
|
698
|
+
} else {
|
699
|
+
return this.revision(type);
|
700
|
+
}
|
701
|
+
},
|
702
|
+
_clientRevision: function (type) {
|
703
|
+
var config = this.configurationForType(type), clientRevision = config && config.clientRevision;
|
704
|
+
if (clientRevision) {
|
705
|
+
return clientRevision;
|
706
|
+
} else {
|
707
|
+
return this.clientRevision(type);
|
708
|
+
}
|
709
|
+
},
|
657
710
|
_addAttribute: function (data, record, attributeName, attributeType) {
|
658
711
|
var key = this._keyForAttributeName(record.constructor, attributeName);
|
659
712
|
var value = get(record, attributeName);
|
@@ -667,6 +720,14 @@
|
|
667
720
|
var clientKey = this._clientKey(type);
|
668
721
|
this.addId(hash, clientKey, this.serializeClientId(id));
|
669
722
|
},
|
723
|
+
_addRevision: function (hash, type, rev) {
|
724
|
+
var revision = this._revision(type);
|
725
|
+
this.addId(hash, revision, this.serializeRevision(rev));
|
726
|
+
},
|
727
|
+
_addClientRevision: function (hash, type, rev) {
|
728
|
+
var revision = this._clientRevision(type);
|
729
|
+
this.addId(hash, revision, this.serializeClientRevision(rev));
|
730
|
+
},
|
670
731
|
_keyForAttributeName: function (type, name) {
|
671
732
|
return this._keyFromMappingOrHook('keyForAttributeName', type, name);
|
672
733
|
},
|
@@ -1311,6 +1372,8 @@
|
|
1311
1372
|
Ep.ModelMixin = Ember.Mixin.create({
|
1312
1373
|
id: null,
|
1313
1374
|
clientId: null,
|
1375
|
+
rev: null,
|
1376
|
+
clientRev: 0,
|
1314
1377
|
session: null,
|
1315
1378
|
errors: null,
|
1316
1379
|
isEqual: function (model) {
|
@@ -1357,17 +1420,15 @@
|
|
1357
1420
|
Ep.Model = Ember.Object.extend(Ember.Copyable, Ep.ModelMixin, {
|
1358
1421
|
isPromise: false,
|
1359
1422
|
isProxy: false,
|
1423
|
+
isNew: true,
|
1360
1424
|
isDeleted: false,
|
1361
1425
|
isLoaded: true,
|
1362
|
-
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1368
|
-
}
|
1369
|
-
return value;
|
1370
|
-
}),
|
1426
|
+
isDirty: Ember.computed(function () {
|
1427
|
+
var session = get(this, 'session');
|
1428
|
+
if (!session)
|
1429
|
+
return false;
|
1430
|
+
return get(session, 'dirtyModels').contains(this);
|
1431
|
+
}).volatile(),
|
1371
1432
|
diff: function (model) {
|
1372
1433
|
var diffs = [];
|
1373
1434
|
this.eachAttribute(function (name, meta) {
|
@@ -1456,7 +1517,10 @@
|
|
1456
1517
|
dest.beginPropertyChanges();
|
1457
1518
|
set(dest, 'id', get(this, 'id'));
|
1458
1519
|
set(dest, 'clientId', get(this, 'clientId'));
|
1520
|
+
set(dest, 'rev', get(this, 'rev'));
|
1521
|
+
set(dest, 'clientRev', get(this, 'clientRev'));
|
1459
1522
|
set(dest, 'errors', Ember.copy(get(this, 'errors')));
|
1523
|
+
set(dest, 'isNew', get(this, 'isNew'));
|
1460
1524
|
set(dest, 'isDeleted', get(this, 'isDeleted'));
|
1461
1525
|
this.eachAttribute(function (name, meta) {
|
1462
1526
|
var left = get(this, name);
|
@@ -1800,7 +1864,10 @@
|
|
1800
1864
|
Ep.ModelProxy = Ember.ObjectProxy.extend(Ember.Copyable, Ep.ModelMixin, {
|
1801
1865
|
id: passThrough('id'),
|
1802
1866
|
clientId: passThrough('clientId'),
|
1867
|
+
rev: passThrough('rev'),
|
1868
|
+
clientRev: passThrough('clientRev'),
|
1803
1869
|
type: passThrough('type'),
|
1870
|
+
isDirty: false,
|
1804
1871
|
isPromise: false,
|
1805
1872
|
isLoaded: passThrough('isLoaded', false),
|
1806
1873
|
isLoading: false,
|
@@ -1966,7 +2033,7 @@
|
|
1966
2033
|
var data = {};
|
1967
2034
|
data[root] = get(this, 'serializer').serialize(model, { includeId: true });
|
1968
2035
|
return this.ajax(this.buildURL(root), 'POST', { data: data }).then(function (json) {
|
1969
|
-
return Ember.run(adapter, '
|
2036
|
+
return Ember.run(adapter, 'didReceiveData', json, model);
|
1970
2037
|
}, function (xhr) {
|
1971
2038
|
throw Ember.run(adapter, 'didError', xhr, model);
|
1972
2039
|
});
|
@@ -2021,16 +2088,6 @@
|
|
2021
2088
|
result = model;
|
2022
2089
|
}
|
2023
2090
|
});
|
2024
|
-
return result || targetModel;
|
2025
|
-
},
|
2026
|
-
didReceiveDataForCreate: function (data, targetModel) {
|
2027
|
-
var result = null;
|
2028
|
-
this.processData(data, function (model) {
|
2029
|
-
if (targetModel && model.isEqual(targetModel)) {
|
2030
|
-
result = model;
|
2031
|
-
}
|
2032
|
-
});
|
2033
|
-
set(targetModel, 'id', get(result, 'id'));
|
2034
2091
|
return result;
|
2035
2092
|
},
|
2036
2093
|
didReceiveDataForLoad: function (data, type, id) {
|
@@ -2199,6 +2256,7 @@
|
|
2199
2256
|
shadows.add(copy);
|
2200
2257
|
}
|
2201
2258
|
}
|
2259
|
+
this._embeddedManager.updateParents(model);
|
2202
2260
|
}, this);
|
2203
2261
|
},
|
2204
2262
|
dirtyEmbeddedTree: function (model, models, shadows, session) {
|
@@ -2311,48 +2369,23 @@
|
|
2311
2369
|
require.define('/lib/rest/operation_graph.js', function (module, exports, __dirname, __filename) {
|
2312
2370
|
require('/lib/rest/operation.js', module);
|
2313
2371
|
var get = Ember.get, set = Ember.set;
|
2314
|
-
var Node = function (model) {
|
2315
|
-
this.op = null;
|
2316
|
-
this.children = Ember.Set.create();
|
2317
|
-
this.parents = Ember.Set.create();
|
2318
|
-
this.dirty = false;
|
2319
|
-
this.dirtyEmbeddedChildren = false;
|
2320
|
-
};
|
2321
|
-
Node.prototype = {
|
2322
|
-
addChild: function (childNode) {
|
2323
|
-
this.children.add(childNode);
|
2324
|
-
childNode.parents.add(this);
|
2325
|
-
},
|
2326
|
-
isRoot: function () {
|
2327
|
-
return this.parents.every(function (parent) {
|
2328
|
-
return !get(parent, 'dirty') && parent.isRoot();
|
2329
|
-
});
|
2330
|
-
},
|
2331
|
-
toString: function (depth) {
|
2332
|
-
if (!depth)
|
2333
|
-
depth = 0;
|
2334
|
-
var prefix = '';
|
2335
|
-
for (var i = 0; i < depth; i++) {
|
2336
|
-
prefix += ' ';
|
2337
|
-
}
|
2338
|
-
return prefix + this.op.toString() + this.children.map(function (child) {
|
2339
|
-
return '\n' + child.toString(depth + 1);
|
2340
|
-
});
|
2341
|
-
}
|
2342
|
-
};
|
2343
2372
|
Ep.OperationGraph = Ember.Object.extend({
|
2344
2373
|
models: null,
|
2345
2374
|
shadows: null,
|
2346
|
-
|
2375
|
+
rootOps: null,
|
2347
2376
|
adapter: null,
|
2348
|
-
nodes: null,
|
2349
2377
|
init: function () {
|
2350
|
-
|
2378
|
+
var graph = this;
|
2379
|
+
this.ops = Ember.MapWithDefault.create({
|
2351
2380
|
defaultValue: function (model) {
|
2352
|
-
return
|
2381
|
+
return Ep.Operation.create({
|
2382
|
+
model: model,
|
2383
|
+
graph: graph,
|
2384
|
+
adapter: get(graph, 'adapter')
|
2385
|
+
});
|
2353
2386
|
}
|
2354
2387
|
});
|
2355
|
-
this.
|
2388
|
+
this.rootOps = Ember.Set.create();
|
2356
2389
|
this.build();
|
2357
2390
|
},
|
2358
2391
|
perform: function () {
|
@@ -2362,63 +2395,60 @@
|
|
2362
2395
|
var adapter = get(this, 'adapter');
|
2363
2396
|
var models = get(this, 'models');
|
2364
2397
|
var shadows = get(this, 'shadows');
|
2365
|
-
var
|
2366
|
-
var
|
2398
|
+
var rootOps = get(this, 'rootOps');
|
2399
|
+
var ops = get(this, 'ops');
|
2367
2400
|
models.forEach(function (model) {
|
2368
2401
|
if (!get(model, 'isLoaded')) {
|
2369
2402
|
return;
|
2370
2403
|
}
|
2371
2404
|
var shadow = shadows.getModel(model);
|
2372
|
-
|
2373
|
-
|
2374
|
-
|
2375
|
-
|
2376
|
-
|
2377
|
-
adapter
|
2378
|
-
|
2379
|
-
|
2380
|
-
|
2381
|
-
var
|
2382
|
-
|
2383
|
-
|
2384
|
-
|
2385
|
-
}
|
2386
|
-
var rels = get(node.op, 'dirtyRelationships');
|
2405
|
+
Ember.assert('Shadow does not exist for non-new model', shadow || get(model, 'isNew'));
|
2406
|
+
var op = ops.get(model);
|
2407
|
+
set(op, 'shadow', shadow);
|
2408
|
+
var isEmbedded = adapter.isEmbedded(model);
|
2409
|
+
if (get(op, 'isDirty') && isEmbedded) {
|
2410
|
+
var rootModel = adapter.findEmbeddedRoot(model, models);
|
2411
|
+
var rootOp = this.getOp(rootModel);
|
2412
|
+
set(rootOp, 'force', true);
|
2413
|
+
var parentModel = adapter._embeddedManager.findParent(model);
|
2414
|
+
var parentOp = this.getOp(parentModel);
|
2415
|
+
parentOp.addChild(op);
|
2416
|
+
}
|
2417
|
+
var rels = get(op, 'dirtyRelationships');
|
2387
2418
|
for (var i = 0; i < rels.length; i++) {
|
2388
2419
|
var d = rels[i];
|
2389
2420
|
var name = d.name;
|
2390
2421
|
var parentModel = model.get(name) || shadows.getModel(d.oldValue);
|
2391
2422
|
if (parentModel) {
|
2392
|
-
|
2393
|
-
|
2394
|
-
parentNode.addChild(node);
|
2423
|
+
var parentOp = this.getOp(parentModel);
|
2424
|
+
parentOp.addChild(op);
|
2395
2425
|
}
|
2396
2426
|
}
|
2397
2427
|
}, this);
|
2398
|
-
|
2399
|
-
if (
|
2400
|
-
|
2428
|
+
ops.forEach(function (model, op) {
|
2429
|
+
if (get(op, 'isDirty') && get(op, 'isRoot')) {
|
2430
|
+
rootOps.add(op);
|
2401
2431
|
}
|
2402
2432
|
}, this);
|
2403
2433
|
},
|
2434
|
+
getOp: function (model) {
|
2435
|
+
var models = get(this, 'models');
|
2436
|
+
return this.ops.get(models.getModel(model));
|
2437
|
+
},
|
2404
2438
|
createPromise: function () {
|
2405
|
-
var
|
2406
|
-
function createNestedPromise(
|
2407
|
-
var promise =
|
2439
|
+
var rootOps = get(this, 'rootOps'), adapter = get(this, 'adapter'), cumulative = [];
|
2440
|
+
function createNestedPromise(op) {
|
2441
|
+
var promise = op.perform();
|
2408
2442
|
promise = promise.then(function (model) {
|
2409
|
-
|
2410
|
-
cumulative.push(model.lazyCopy());
|
2411
|
-
} else {
|
2412
|
-
cumulative.push(model);
|
2413
|
-
}
|
2443
|
+
cumulative.push(model);
|
2414
2444
|
return model;
|
2415
2445
|
}, function (model) {
|
2416
2446
|
cumulative.push(model);
|
2417
2447
|
throw model;
|
2418
2448
|
});
|
2419
|
-
if (
|
2449
|
+
if (op.children.length > 0) {
|
2420
2450
|
promise = promise.then(function (model) {
|
2421
|
-
var childPromises =
|
2451
|
+
var childPromises = op.children.map(createNestedPromise);
|
2422
2452
|
return Ember.RSVP.all(childPromises).then(function (models) {
|
2423
2453
|
adapter.rebuildRelationships(models, model);
|
2424
2454
|
return model;
|
@@ -2427,7 +2457,7 @@
|
|
2427
2457
|
}
|
2428
2458
|
return promise;
|
2429
2459
|
}
|
2430
|
-
return Ember.RSVP.all(
|
2460
|
+
return Ember.RSVP.all(rootOps.map(createNestedPromise)).then(function () {
|
2431
2461
|
return cumulative;
|
2432
2462
|
}, function (err) {
|
2433
2463
|
throw cumulative;
|
@@ -2435,9 +2465,9 @@
|
|
2435
2465
|
},
|
2436
2466
|
toStringExtension: function () {
|
2437
2467
|
var result = '';
|
2438
|
-
var
|
2439
|
-
|
2440
|
-
result += '\n' +
|
2468
|
+
var rootOps = get(this, 'rootOps');
|
2469
|
+
rootOps.forEach(function (op) {
|
2470
|
+
result += '\n' + op.toString(1);
|
2441
2471
|
});
|
2442
2472
|
return result + '\n';
|
2443
2473
|
}
|
@@ -2449,6 +2479,8 @@
|
|
2449
2479
|
model: null,
|
2450
2480
|
shadow: null,
|
2451
2481
|
adapter: null,
|
2482
|
+
_promise: null,
|
2483
|
+
force: false,
|
2452
2484
|
init: function () {
|
2453
2485
|
this.children = Ember.Set.create();
|
2454
2486
|
this.parents = Ember.Set.create();
|
@@ -2478,6 +2510,9 @@
|
|
2478
2510
|
return rels;
|
2479
2511
|
}),
|
2480
2512
|
isDirty: Ember.computed(function () {
|
2513
|
+
return !!get(this, 'dirtyType');
|
2514
|
+
}),
|
2515
|
+
isDirtyFromUpdates: Ember.computed(function () {
|
2481
2516
|
var model = get(this, 'model'), shadow = get(this, 'shadow'), adapter = get(this, 'adapter');
|
2482
2517
|
var diff = model.diff(shadow);
|
2483
2518
|
var dirty = false;
|
@@ -2498,17 +2533,20 @@
|
|
2498
2533
|
return 'created';
|
2499
2534
|
} else if (get(model, 'isDeleted')) {
|
2500
2535
|
return 'deleted';
|
2501
|
-
} else if (get(this, '
|
2536
|
+
} else if (get(this, 'isDirtyFromUpdates') || get(this, 'force')) {
|
2502
2537
|
return 'updated';
|
2503
2538
|
}
|
2504
2539
|
}),
|
2505
|
-
perform: function (
|
2540
|
+
perform: function () {
|
2541
|
+
if (this._promise)
|
2542
|
+
return this._promise;
|
2506
2543
|
var adapter = get(this, 'adapter'), dirtyType = get(this, 'dirtyType'), model = get(this, 'model'), shadow = get(this, 'shadow'), promise;
|
2507
|
-
if (!dirtyType && forceUpdate) {
|
2508
|
-
dirtyType = 'updated';
|
2509
|
-
}
|
2510
2544
|
if (!dirtyType || !adapter.shouldSave(model)) {
|
2511
|
-
|
2545
|
+
if (adapter.isEmbedded(model)) {
|
2546
|
+
promise = this._promiseFromEmbeddedParent();
|
2547
|
+
} else {
|
2548
|
+
promise = Ember.RSVP.resolve();
|
2549
|
+
}
|
2512
2550
|
} else if (dirtyType === 'created') {
|
2513
2551
|
promise = adapter.create(model);
|
2514
2552
|
} else if (dirtyType === 'updated') {
|
@@ -2516,17 +2554,61 @@
|
|
2516
2554
|
} else if (dirtyType === 'deleted') {
|
2517
2555
|
promise = adapter.deleteModel(model);
|
2518
2556
|
}
|
2519
|
-
|
2557
|
+
promise = promise.then(function (serverModel) {
|
2558
|
+
if (!get(model, 'id')) {
|
2559
|
+
set(model, 'id', get(serverModel, 'id'));
|
2560
|
+
}
|
2561
|
+
if (!serverModel) {
|
2562
|
+
serverModel = model;
|
2563
|
+
} else if (!get(serverModel, 'clientRev')) {
|
2564
|
+
set(serverModel, 'clientRev', get(model, 'clientRev'));
|
2565
|
+
}
|
2566
|
+
return serverModel;
|
2567
|
+
}, function (serverModel) {
|
2520
2568
|
if (shadow) {
|
2521
|
-
shadow.set('errors',
|
2569
|
+
shadow.set('errors', serverModel.get('errors'));
|
2522
2570
|
throw shadow;
|
2523
2571
|
}
|
2524
|
-
throw
|
2572
|
+
throw serverModel;
|
2573
|
+
});
|
2574
|
+
return this._promise = promise;
|
2575
|
+
},
|
2576
|
+
_embeddedParent: Ember.computed(function () {
|
2577
|
+
var model = get(this, 'model'), parentModel = get(this, 'adapter')._embeddedManager.findParent(model), graph = get(this, 'graph');
|
2578
|
+
Ember.assert('Embedded parent does not exist!', parentModel);
|
2579
|
+
return graph.getOp(parentModel);
|
2580
|
+
}),
|
2581
|
+
_promiseFromEmbeddedParent: function () {
|
2582
|
+
var serializer = get(this, 'adapter.serializer');
|
2583
|
+
var model = this.model;
|
2584
|
+
function findInParent(parentModel) {
|
2585
|
+
var res = null;
|
2586
|
+
serializer.eachEmbeddedRecord(parentModel, function (child, embeddedType) {
|
2587
|
+
if (res)
|
2588
|
+
return;
|
2589
|
+
if (child.isEqual(model))
|
2590
|
+
res = child;
|
2591
|
+
});
|
2592
|
+
return res;
|
2593
|
+
}
|
2594
|
+
return get(this, '_embeddedParent').perform().then(function (parent) {
|
2595
|
+
return findInParent(parent);
|
2596
|
+
}, function (parent) {
|
2597
|
+
throw findInParent(parent);
|
2525
2598
|
});
|
2526
2599
|
},
|
2527
2600
|
toStringExtension: function () {
|
2528
2601
|
return '( ' + get(this, 'dirtyType') + ' ' + get(this, 'model') + ' )';
|
2529
|
-
}
|
2602
|
+
},
|
2603
|
+
addChild: function (child) {
|
2604
|
+
this.children.add(child);
|
2605
|
+
child.parents.add(this);
|
2606
|
+
},
|
2607
|
+
isRoot: Ember.computed(function () {
|
2608
|
+
return this.parents.every(function (parent) {
|
2609
|
+
return !get(parent, 'isDirty') && get(parent, 'isRoot');
|
2610
|
+
});
|
2611
|
+
}).volatile()
|
2530
2612
|
});
|
2531
2613
|
});
|
2532
2614
|
require.define('/lib/rest/embedded_manager.js', function (module, exports, __dirname, __filename) {
|
@@ -2878,34 +2960,70 @@
|
|
2878
2960
|
var get = Ember.get, set = Ember.set;
|
2879
2961
|
Ep.Session.reopen({
|
2880
2962
|
merge: function (model, strategy) {
|
2881
|
-
var shadows = get(this, 'shadows'), newModels = get(this, 'newModels');
|
2882
2963
|
this.reifyClientId(model);
|
2883
|
-
if (
|
2884
|
-
|
2885
|
-
|
2886
|
-
|
2887
|
-
|
2888
|
-
|
2889
|
-
|
2890
|
-
|
2891
|
-
|
2964
|
+
if (get(model, 'hasErrors')) {
|
2965
|
+
return this._mergeError(model, strategy);
|
2966
|
+
} else {
|
2967
|
+
return this._mergeSuccess(model, strategy);
|
2968
|
+
}
|
2969
|
+
},
|
2970
|
+
_mergeSuccess: function (model, strategy) {
|
2971
|
+
var models = get(this, 'models'), shadows = get(this, 'shadows'), newModels = get(this, 'newModels'), originals = get(this, 'originals'), merged, ancestor, existing = models.getModel(model);
|
2972
|
+
if (existing && this._containsRev(existing, model)) {
|
2973
|
+
return existing;
|
2974
|
+
}
|
2975
|
+
var hasClientChanges = !existing || this._containsClientRev(model, existing);
|
2976
|
+
if (hasClientChanges) {
|
2977
|
+
ancestor = shadows.getModel(model);
|
2978
|
+
} else {
|
2979
|
+
ancestor = originals.getModel(model);
|
2980
|
+
}
|
2981
|
+
this.suspendDirtyChecking(function () {
|
2982
|
+
merged = this._mergeModel(existing, ancestor, model, strategy);
|
2983
|
+
}, this);
|
2984
|
+
if (hasClientChanges) {
|
2985
|
+
if (get(merged, 'isDeleted')) {
|
2986
|
+
this.remove(merged);
|
2987
|
+
} else {
|
2988
|
+
if (shadows.contains(model) && get(model, 'isLoaded')) {
|
2989
|
+
shadows.add(model);
|
2990
|
+
}
|
2991
|
+
originals.remove(model);
|
2992
|
+
if (!get(merged, 'isNew')) {
|
2993
|
+
newModels.remove(merged);
|
2994
|
+
}
|
2892
2995
|
}
|
2893
|
-
newModels.remove(model);
|
2894
2996
|
} else {
|
2997
|
+
}
|
2998
|
+
return merged;
|
2999
|
+
},
|
3000
|
+
_mergeError: function (model, strategy) {
|
3001
|
+
var models = get(this, 'models'), shadows = get(this, 'shadows'), newModels = get(this, 'newModels'), originals = get(this, 'originals'), merged, ancestor, existing = models.getModel(model);
|
3002
|
+
if (!existing) {
|
3003
|
+
Ember.assert('Errors returned for non-existant model: ' + model.toString(), model instanceof Ep.LoadError);
|
3004
|
+
return model;
|
3005
|
+
}
|
3006
|
+
ancestor = originals.getModel(model);
|
3007
|
+
if (ancestor && !this._containsRev(existing, model)) {
|
2895
3008
|
this.suspendDirtyChecking(function () {
|
2896
|
-
merged = this.
|
3009
|
+
merged = this._mergeModel(existing, ancestor, model, strategy);
|
2897
3010
|
}, this);
|
2898
|
-
|
3011
|
+
} else {
|
3012
|
+
merged = existing;
|
2899
3013
|
}
|
3014
|
+
set(merged, 'errors', Ember.copy(get(model, 'errors')));
|
3015
|
+
shadows.add(model);
|
3016
|
+
originals.remove(model);
|
2900
3017
|
return merged;
|
2901
3018
|
},
|
2902
|
-
|
2903
|
-
|
3019
|
+
_mergeModel: function (dest, ancestor, model, strategy) {
|
3020
|
+
if (!strategy)
|
3021
|
+
strategy = get(this, 'mergeStrategy').create({ session: this });
|
2904
3022
|
if (model === dest) {
|
2905
3023
|
return model;
|
2906
3024
|
}
|
2907
3025
|
if (get(model, 'isPromise')) {
|
2908
|
-
return this.
|
3026
|
+
return this._mergePromise(dest, ancestor, model, strategy);
|
2909
3027
|
}
|
2910
3028
|
var promise;
|
2911
3029
|
if (dest && get(dest, 'isPromise')) {
|
@@ -2918,18 +3036,24 @@
|
|
2918
3036
|
promise.resolve(dest);
|
2919
3037
|
}
|
2920
3038
|
}
|
3039
|
+
if (!get(model, 'hasErrors')) {
|
3040
|
+
set(dest, 'isNew', false);
|
3041
|
+
}
|
2921
3042
|
set(dest, 'id', get(model, 'id'));
|
2922
3043
|
set(dest, 'clientId', get(model, 'clientId'));
|
3044
|
+
set(dest, 'rev', get(model, 'rev'));
|
2923
3045
|
set(dest, 'isDeleted', get(model, 'isDeleted'));
|
2924
|
-
set(dest, 'errors', Ember.copy(get(model, 'errors')));
|
2925
3046
|
this.adopt(dest);
|
2926
|
-
|
3047
|
+
if (!ancestor) {
|
3048
|
+
ancestor = dest;
|
3049
|
+
}
|
3050
|
+
strategy.merge(dest, ancestor, model);
|
2927
3051
|
return dest;
|
2928
3052
|
},
|
2929
|
-
|
3053
|
+
_mergePromise: function (dest, ancestor, promise, strategy) {
|
2930
3054
|
var content = get(promise, 'content');
|
2931
3055
|
if (content) {
|
2932
|
-
return this.merge(content, strategy);
|
3056
|
+
return this.merge(dest, ancestor, content, strategy);
|
2933
3057
|
}
|
2934
3058
|
if (!dest) {
|
2935
3059
|
dest = promise.lazyCopy();
|
@@ -2937,14 +3061,15 @@
|
|
2937
3061
|
}
|
2938
3062
|
return dest;
|
2939
3063
|
},
|
2940
|
-
|
2941
|
-
|
2942
|
-
|
2943
|
-
|
2944
|
-
return
|
2945
|
-
|
2946
|
-
|
2947
|
-
|
3064
|
+
_containsRev: function (modelA, modelB) {
|
3065
|
+
if (!get(modelA, 'rev'))
|
3066
|
+
return false;
|
3067
|
+
if (!get(modelB, 'rev'))
|
3068
|
+
return false;
|
3069
|
+
return get(modelA, 'rev') >= get(modelB, 'rev');
|
3070
|
+
},
|
3071
|
+
_containsClientRev: function (modelA, modelB) {
|
3072
|
+
return get(modelA, 'clientRev') >= get(modelB, 'clientRev');
|
2948
3073
|
}
|
2949
3074
|
});
|
2950
3075
|
});
|
@@ -2965,6 +3090,7 @@
|
|
2965
3090
|
this.collectionManager = Ep.CollectionManager.create();
|
2966
3091
|
this.belongsToManager = Ep.BelongsToManager.create();
|
2967
3092
|
this.shadows = Ep.ModelSet.create();
|
3093
|
+
this.originals = Ep.ModelSet.create();
|
2968
3094
|
this.newModels = Ep.ModelSet.create();
|
2969
3095
|
},
|
2970
3096
|
create: function (type, hash) {
|
@@ -3042,6 +3168,11 @@
|
|
3042
3168
|
}, this);
|
3043
3169
|
return dest;
|
3044
3170
|
},
|
3171
|
+
remove: function (model) {
|
3172
|
+
get(this, 'models').remove(model);
|
3173
|
+
get(this, 'shadows').remove(model);
|
3174
|
+
get(this, 'originals').remove(model);
|
3175
|
+
},
|
3045
3176
|
update: function (model) {
|
3046
3177
|
this.reifyClientId(model);
|
3047
3178
|
if (get(model, 'isProxy')) {
|
@@ -3135,7 +3266,10 @@
|
|
3135
3266
|
});
|
3136
3267
|
},
|
3137
3268
|
flush: function () {
|
3138
|
-
var session = this, dirtyModels = get(this, 'dirtyModels'), shadows = get(this, 'shadows');
|
3269
|
+
var session = this, dirtyModels = get(this, 'dirtyModels'), newModels = get(this, 'newModels'), shadows = get(this, 'shadows');
|
3270
|
+
dirtyModels.forEach(function (model) {
|
3271
|
+
model.incrementProperty('clientRev');
|
3272
|
+
}, this);
|
3139
3273
|
var promise = this.adapter.flush(this).then(function (models) {
|
3140
3274
|
var res = models.map(function (model) {
|
3141
3275
|
return session.merge(model);
|
@@ -3148,8 +3282,14 @@
|
|
3148
3282
|
throw res;
|
3149
3283
|
});
|
3150
3284
|
dirtyModels.forEach(function (model) {
|
3151
|
-
this.
|
3285
|
+
var original = this.originals.getModel(model);
|
3286
|
+
var shadow = this.shadows.getModel(model);
|
3287
|
+
if (shadow && (!original || original.get('rev') < shadow.get('rev'))) {
|
3288
|
+
this.originals.add(shadow);
|
3289
|
+
}
|
3290
|
+
this.shadows.remove(model);
|
3152
3291
|
}, this);
|
3292
|
+
newModels.clear();
|
3153
3293
|
return promise;
|
3154
3294
|
},
|
3155
3295
|
getModel: function (model) {
|
@@ -3189,6 +3329,7 @@
|
|
3189
3329
|
this.collectionManager.destroy();
|
3190
3330
|
this.belongsToManager.destroy();
|
3191
3331
|
this.shadows.destroy();
|
3332
|
+
this.originals.destroy();
|
3192
3333
|
this.newModels.destroy();
|
3193
3334
|
},
|
3194
3335
|
dirtyModels: Ember.computed(function () {
|
@@ -3243,23 +3384,21 @@
|
|
3243
3384
|
init: function () {
|
3244
3385
|
this.cache = Ep.ModelSet.create();
|
3245
3386
|
},
|
3246
|
-
merge: function (
|
3387
|
+
merge: function (ours, ancestor, theirs) {
|
3247
3388
|
if (this.cache.contains(ours))
|
3248
3389
|
return ours;
|
3249
3390
|
this.cache.addObject(theirs);
|
3250
3391
|
ours.beginPropertyChanges();
|
3251
|
-
|
3252
|
-
|
3253
|
-
this.mergeAttributes(theirs, ours, original);
|
3254
|
-
this.mergeRelationships(theirs, ours, original);
|
3392
|
+
this.mergeAttributes(ours, ancestor, theirs);
|
3393
|
+
this.mergeRelationships(ours, ancestor, theirs);
|
3255
3394
|
ours.endPropertyChanges();
|
3256
3395
|
return ours;
|
3257
3396
|
},
|
3258
|
-
mergeAttributes: function (
|
3397
|
+
mergeAttributes: function (ours, ancestor, theirs) {
|
3259
3398
|
ours.eachAttribute(function (name, meta) {
|
3260
3399
|
var oursValue = get(ours, name);
|
3261
3400
|
var theirsValue = get(theirs, name);
|
3262
|
-
var originalValue = get(
|
3401
|
+
var originalValue = get(ancestor, name);
|
3263
3402
|
if (oursValue === theirsValue)
|
3264
3403
|
return;
|
3265
3404
|
if (oursValue === originalValue) {
|
@@ -3267,13 +3406,13 @@
|
|
3267
3406
|
}
|
3268
3407
|
});
|
3269
3408
|
},
|
3270
|
-
mergeRelationships: function (
|
3409
|
+
mergeRelationships: function (ours, ancestor, theirs) {
|
3271
3410
|
var session = get(this, 'session');
|
3272
3411
|
ours.eachRelationship(function (name, relationship) {
|
3273
3412
|
if (relationship.kind === 'belongsTo') {
|
3274
3413
|
var oursValue = get(ours, name);
|
3275
3414
|
var theirsValue = get(theirs, name);
|
3276
|
-
var originalValue = get(
|
3415
|
+
var originalValue = get(ancestor, name);
|
3277
3416
|
var merged = mergeIfPresent(session, theirsValue, this);
|
3278
3417
|
if (isEqual(oursValue, originalValue)) {
|
3279
3418
|
set(ours, name, merged);
|
@@ -3281,7 +3420,7 @@
|
|
3281
3420
|
} else if (relationship.kind === 'hasMany') {
|
3282
3421
|
var theirChildren = get(theirs, name);
|
3283
3422
|
var ourChildren = get(ours, name);
|
3284
|
-
var originalChildren = get(
|
3423
|
+
var originalChildren = get(ancestor, name);
|
3285
3424
|
if (isEqual(ourChildren, originalChildren)) {
|
3286
3425
|
var existing = Ep.ModelSet.create();
|
3287
3426
|
existing.addObjects(ourChildren);
|
@@ -3310,7 +3449,7 @@
|
|
3310
3449
|
init: function () {
|
3311
3450
|
this.cache = Ep.ModelSet.create();
|
3312
3451
|
},
|
3313
|
-
merge: function (
|
3452
|
+
merge: function (dest, ancestor, model) {
|
3314
3453
|
if (this.cache.contains(model))
|
3315
3454
|
return dest;
|
3316
3455
|
this.cache.addObject(model);
|