serialize: function(type, data) { var serialized = clone(data); delete serialized.__normalized; delete serialized.__rev; if (this.schema.idField !== this.schema.remoteIdField) { delete serialized[this.schema.idField]; } if (serialized.__rel) { var relKeys = Object.keys(serialized.__rel); if (relKeys.length > 0) { var links = {}; relKeys.forEach(function(key) { var link = serialized.__rel[key]; if (typeof link === 'object') { links[key] = Object.keys(link); } else { links[key] = link; } }); serialized.links = links; } delete serialized.__rel; } return serialized; },
memorySource.find("planet").then(function(planets) { equal(planets.length, 1, 'found one planet'); start(); var planet = clone(planets[0]); planet.classification = 'Gas giant'; memorySource.update("planet", planet).then(function() { ok(true, 'planet updated'); start(); }); });
test("`clone` creates a deep clone of an object's own properties", function() { var obj = { a: 1, b: '2', c: ['3', {d: '4', e: ['5', '6']}, 7], f: new Date(), g: /123/g }; var copy = clone(obj); deepEqual(obj, copy, 'clone is deeply equal to original'); notStrictEqual(obj, copy, 'clone is not strictly equal to original'); });
memorySource.add('planet', {name: 'Jupiter', classification: 'gas giant'}).then(function(planet) { planet = clone(planet); planet.name = 'Earth'; memorySource.update('planet', planet).then(function() { start(); var updatedPlanet = memorySource.retrieve(['planet', planet.__id]); equal(memorySource.length('planet'), 1, 'memory source should contain one record'); equal(updatedPlanet.__id, planet.__id, 'orbit id should be defined'); equal(updatedPlanet.id, '12345', 'server id should be defined'); equal(updatedPlanet.name, 'Earth', 'name should match'); equal(updatedPlanet.classification, 'gas giant', 'classification was not updated'); equal(localSource.length('planet'), 1, 'local source should contain one record'); verifyLocalStorageContainsRecord(localSource.namespace, 'planet', updatedPlanet.__id, updatedPlanet); }); });
memorySource.add('planet', {name: 'Jupiter', classification: 'gas giant'}).then(function(record) { equal(memorySource.length('planet'), 1, 'memory source - inserted - should contain one record'); ok(record.__id, 'memory source - inserted - orbit id should be defined'); equal(record.id, undefined, 'memory source - inserted - server id should NOT be defined yet'); equal(record.name, 'Jupiter', 'memory source - inserted - name - Jupiter'); equal(record.classification, 'gas giant', 'memory source - inserted - classification - gas giant'); server.respond('POST', '/planets', function(xhr) { deepEqual(JSON.parse(xhr.requestBody), {data: {type: 'planets', attributes: {name: 'Jupiter', classification: 'gas giant'}}}, 'POST request'); xhr.respond(201, {'Content-Type': 'application/json'}, JSON.stringify({data: {type: 'planets', id: '12345', attributes: {name: 'Jupiter', classification: 'gas giant'}}})); }); record = clone(record); record.name = 'Earth'; return memorySource.update('planet', record); });
_serialize: function(type, data) { var serialized = clone(data); delete serialized[this.schema.idField]; if (serialized.links) { var links = {}; for (var i in serialized.links) { var link = serialized.links[i]; if (typeof link === 'object') { links[i] = Object.keys(link); } else { links[i] = link; } } serialized.links = links; } return serialized; },
serialize: function(type, data) { var serialized = clone(data); delete serialized.__normalized; delete serialized.__rev; delete serialized.__meta; if (this.schema.idField !== this.schema.remoteIdField) { delete serialized[this.schema.idField]; } if (serialized.__rel) { var relKeys = Object.keys(serialized.__rel); if (relKeys.length > 0) { var links = {}; relKeys.forEach(function(key) { var link = serialized.__rel[key]; if (link !== null && typeof link === 'object') { links[key] = Object.keys(link); } else { links[key] = link; } }); serialized.links = links; } delete serialized.__rel; } var primaryKey = this.keyFromType(type); var payload = {}; payload[primaryKey] = serialized; return payload; },
sources.forEach(function(source) { source = clone(source); this._mergeModelFields(base.keys, source.keys); this._mergeModelFields(base.attributes, source.attributes); this._mergeModelFields(base.links, source.links); }, this);
var diffs = function(a, b, options) { if (a === b) { return undefined; } else { options = options || {}; var ignore = arrayToOptions(options.ignore), basePath = options.basePath || ''; if (Object.prototype.toString.call(basePath) === '[object Array]') { basePath = basePath.join('/'); } var type = Object.prototype.toString.call(a); if (type === Object.prototype.toString.call(b)) { if (typeof a === 'object') { var i, d; if (type === '[object Array]') { var aLength = a.length, bLength = b.length, maxLength = bLength > aLength ? bLength : aLength, match, ai = 0, bi = 0, bj; for (i = 0; i < maxLength; i++) { if (ai >= aLength) { if (d === undefined) d = []; d.push({op: 'add', path: basePath + '/' + bi, value: clone(b[bi])}); bi++; } else if (bi >= bLength) { if (d === undefined) d = []; d.push({op: 'remove', path: basePath + '/' + ai}); ai++; } else if (!eq(a[ai], b[bi])) { match = -1; for (bj = bi + 1; bj < bLength; bj++) { if (eq(a[ai], b[bj])) { match = bj; break; } } if (match === -1) { if (d === undefined) d = []; d.push({op: 'remove', path: basePath + '/' + ai}); ai++; } else { if (d === undefined) d = []; d.push({op: 'add', path: basePath + '/' + bi, value: clone(b[bi])}); bi++; } } else { ai++; bi++; } } } else { // general (non-array) object for (i in b) { if (!ignore[i] && b.hasOwnProperty(i)) { if (a[i] === undefined) { if (d === undefined) d = []; d.push({op: 'add', path: basePath + '/' + i, value: clone(b[i])}); } else if (!eq(a[i], b[i])) { if (d === undefined) d = []; d = d.concat(diffs(a[i], b[i], {basePath: basePath + '/' + i})); } } } for (i in a) { if (!ignore[i] && a.hasOwnProperty(i)) { if (b[i] === undefined) { if (d === undefined) d = []; d.push({op: 'remove', path: basePath + '/' + i}); } } } } return d; } else if (eq(a, b)) { return undefined; } } return [{op: 'replace', path: basePath, value: clone(b)}]; } };