Skip to content

Commit 4f04f3c

Browse files
committed
New API for creating a new instance of an object
1 parent 0c2dae1 commit 4f04f3c

File tree

4 files changed

+129
-1
lines changed

4 files changed

+129
-1
lines changed

src/ParseObject.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -775,7 +775,7 @@ export default class ParseObject {
775775
}
776776

777777
/**
778-
* Creates a new model with identical attributes to this one.
778+
* Creates a new model with identical attributes to this one, similar to Backbone.Model's clone()
779779
* @method clone
780780
* @return {Parse.Object}
781781
*/
@@ -803,6 +803,27 @@ export default class ParseObject {
803803
return clone;
804804
}
805805

806+
/**
807+
* Creates a new instance of this object. Not to be confused with clone()
808+
* @method newInstance
809+
* @return {Parse.Object}
810+
*/
811+
newInstance(): any {
812+
let clone = new this.constructor();
813+
if (!clone.className) {
814+
clone.className = this.className;
815+
}
816+
clone.id = this.id;
817+
if (singleInstance) {
818+
// Just return an object with the right id
819+
return clone;
820+
}
821+
822+
let stateController = CoreManager.getObjectStateController();
823+
stateController.duplicateState(this._getStateIdentifier(), clone._getStateIdentifier());
824+
return clone;
825+
}
826+
806827
/**
807828
* Returns true if this object has never been saved to Parse.
808829
* @method isNew

src/UniqueInstanceStateController.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,23 @@ export function enqueueTask(obj: ParseObject, task: () => ParsePromise): ParsePr
123123
return state.tasks.enqueue(task);
124124
}
125125

126+
export function duplicateState(source: ParseObject, dest: ParseObject): void {
127+
let oldState = initializeState(source);
128+
let newState = initializeState(dest);
129+
for (let key in oldState.serverData) {
130+
newState.serverData[key] = oldState.serverData[key];
131+
}
132+
for (let index = 0; index < oldState.pendingOps.length; index++) {
133+
for (let key in oldState.pendingOps[index]) {
134+
newState.pendingOps[index][key] = oldState.pendingOps[index][key];
135+
}
136+
}
137+
for (let key in oldState.objectCache) {
138+
newState.objectCache[key] = oldState.objectCache[key];
139+
}
140+
newState.existed = oldState.existed;
141+
}
142+
126143
export function clearAllState() {
127144
objectState = new WeakMap();
128145
}

src/__tests__/ParseObject-test.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1720,6 +1720,20 @@ describe('ObjectController', () => {
17201720

17211721
xhrs[0].onreadystatechange();
17221722
});
1723+
1724+
it('can create a new instance of an object', () => {
1725+
let o = ParseObject.fromJSON({
1726+
className: 'Clone',
1727+
objectId: 'C12',
1728+
});
1729+
let o2 = o.newInstance();
1730+
expect(o.id).toBe(o2.id);
1731+
expect(o.className).toBe(o2.className);
1732+
o.set({ valid: true });
1733+
expect(o2.get('valid')).toBe(true);
1734+
1735+
expect(o).not.toBe(o2);
1736+
});
17231737
});
17241738

17251739
describe('ParseObject (unique instance mode)', () => {
@@ -1902,6 +1916,21 @@ describe('ParseObject (unique instance mode)', () => {
19021916
expect(o.has('name')).toBe(false);
19031917
expect(o2.has('name')).toBe(true);
19041918
});
1919+
1920+
it('can create a new instance of an object', () => {
1921+
let o = ParseObject.fromJSON({
1922+
className: 'Clone',
1923+
objectId: 'C14',
1924+
});
1925+
let o2 = o.newInstance();
1926+
expect(o.id).toBe(o2.id);
1927+
expect(o.className).toBe(o2.className);
1928+
expect(o).not.toBe(o2);
1929+
o.set({ valid: true });
1930+
expect(o2.get('valid')).toBe(undefined);
1931+
o2 = o.newInstance();
1932+
expect(o2.get('valid')).toBe(true);
1933+
});
19051934
});
19061935

19071936
class MyObject extends ParseObject {

src/__tests__/UniqueInstanceStateController-test.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,4 +420,65 @@ describe('UniqueInstanceStateController', () => {
420420
closure();
421421
}
422422
});
423+
424+
it('can duplicate the state of an object', () => {
425+
let obj = new ParseObject();
426+
UniqueInstanceStateController.setServerData(obj, { counter: 12, name: 'original' });
427+
let setCount = new ParseOps.SetOp(44);
428+
let setValid = new ParseOps.SetOp(true);
429+
UniqueInstanceStateController.setPendingOp(obj, 'counter', setCount);
430+
UniqueInstanceStateController.setPendingOp(obj, 'valid', setValid);
431+
432+
let duplicate = new ParseObject();
433+
UniqueInstanceStateController.duplicateState(obj, duplicate);
434+
expect(UniqueInstanceStateController.getState(duplicate)).toEqual({
435+
serverData: { counter: 12, name: 'original' },
436+
pendingOps: [{ counter: setCount, valid: setValid }],
437+
objectCache: {},
438+
tasks: new TaskQueue(),
439+
existed: false
440+
});
441+
442+
UniqueInstanceStateController.setServerData(duplicate, { name: 'duplicate' });
443+
expect(UniqueInstanceStateController.getState(obj)).toEqual({
444+
serverData: { counter: 12, name: 'original' },
445+
pendingOps: [{ counter: setCount, valid: setValid }],
446+
objectCache: {},
447+
tasks: new TaskQueue(),
448+
existed: false
449+
});
450+
expect(UniqueInstanceStateController.getState(duplicate)).toEqual({
451+
serverData: { counter: 12, name: 'duplicate' },
452+
pendingOps: [{ counter: setCount, valid: setValid }],
453+
objectCache: {},
454+
tasks: new TaskQueue(),
455+
existed: false
456+
});
457+
458+
UniqueInstanceStateController.commitServerChanges(obj, { o: { a: 12 } });
459+
expect(UniqueInstanceStateController.getState(obj)).toEqual({
460+
serverData: { counter: 12, name: 'original', o: { a: 12 } },
461+
pendingOps: [{ counter: setCount, valid: setValid }],
462+
objectCache: { o: '{"a":12}' },
463+
tasks: new TaskQueue(),
464+
existed: false
465+
});
466+
expect(UniqueInstanceStateController.getState(duplicate)).toEqual({
467+
serverData: { counter: 12, name: 'duplicate' },
468+
pendingOps: [{ counter: setCount, valid: setValid }],
469+
objectCache: {},
470+
tasks: new TaskQueue(),
471+
existed: false
472+
});
473+
474+
let otherDup = new ParseObject();
475+
UniqueInstanceStateController.duplicateState(obj, otherDup);
476+
expect(UniqueInstanceStateController.getState(otherDup)).toEqual({
477+
serverData: { counter: 12, name: 'original', o: { a: 12 } },
478+
pendingOps: [{ counter: setCount, valid: setValid }],
479+
objectCache: { o: '{"a":12}' },
480+
tasks: new TaskQueue(),
481+
existed: false
482+
});
483+
});
423484
});

0 commit comments

Comments
 (0)