Skip to content

Commit c061e2f

Browse files
RaschidJFRdavimacedo
authored andcommitted
feat(ParseObject): Add option cascadeSave to save() (#881)
* feat(ParseObject): Add option `cascadeSave` to save() Closes #864 * fix(ParseObject): Safe check for unsaved in save() * refactor(ParseObject): `cascadeSave` won't save new objects Nested objects who have not been saved will be ignored when setting `cascadeSave: true`, so save() will throw "Cannot create Pointer to an unsaved ParseObject".
1 parent 4023bdd commit c061e2f

File tree

2 files changed

+47
-3
lines changed

2 files changed

+47
-3
lines changed

integration/test/ParseObjectTest.js

+38
Original file line numberDiff line numberDiff line change
@@ -934,6 +934,44 @@ describe('Parse Object', () => {
934934
});
935935
});
936936

937+
it('can skip cascade saving as per request', async(done) => {
938+
const Parent = Parse.Object.extend('Parent');
939+
const Child = Parse.Object.extend('Child');
940+
941+
const parent = new Parent();
942+
const child1 = new Child();
943+
const child2 = new Child();
944+
const child3 = new Child();
945+
946+
child1.set('name', 'rob');
947+
child2.set('name', 'sansa');
948+
child3.set('name', 'john');
949+
parent.set('children', [child1, child2]);
950+
parent.set('bastard', child3);
951+
952+
expect(parent.save).toThrow();
953+
let results = await new Parse.Query(Child).find();
954+
assert.equal(results.length, 0);
955+
956+
await parent.save(null, { cascadeSave: true });
957+
results = await new Parse.Query(Child).find();
958+
assert.equal(results.length, 3);
959+
960+
parent.set('dead', true);
961+
child1.set('dead', true);
962+
await parent.save(null);
963+
const rob = await new Parse.Query(Child).equalTo('name', 'rob').first();
964+
expect(rob.get('dead')).toBe(true);
965+
966+
parent.set('lastname', 'stark');
967+
child3.set('lastname', 'stark');
968+
await parent.save(null, { cascadeSave: false });
969+
const john = await new Parse.Query(Child).doesNotExist('lastname').first();
970+
expect(john.get('lastname')).toBeUndefined();
971+
972+
done();
973+
});
974+
937975
it('can do two saves at the same time', (done) => {
938976
const object = new TestObject();
939977
let firstSave = true;

src/ParseObject.js

+9-3
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ type SaveParams = {
5454
body: AttributeMap;
5555
};
5656

57+
type SaveOptions = FullOptions & {
58+
cascadeSave?: boolean
59+
}
60+
5761
const DEFAULT_BATCH_SIZE = 20;
5862

5963
// Mapping of class names to constructors, so we can populate objects from the
@@ -1131,6 +1135,7 @@ class ParseObject {
11311135
* be used for this request.
11321136
* <li>sessionToken: A valid session token, used for making a request on
11331137
* behalf of a specific user.
1138+
* <li>cascadeSave: If `false`, nested objects will not be saved (default is `true`).
11341139
* </ul>
11351140
* </li>
11361141
* </ul>
@@ -1143,15 +1148,16 @@ class ParseObject {
11431148
* be used for this request.
11441149
* <li>sessionToken: A valid session token, used for making a request on
11451150
* behalf of a specific user.
1151+
* <li>cascadeSave: If `false`, nested objects will not be saved (default is `true`).
11461152
* </ul>
11471153
*
11481154
* @return {Promise} A promise that is fulfilled when the save
11491155
* completes.
11501156
*/
11511157
save(
11521158
arg1: ?string | { [attr: string]: mixed },
1153-
arg2: FullOptions | mixed,
1154-
arg3?: FullOptions
1159+
arg2: SaveOptions | mixed,
1160+
arg3?: SaveOptions
11551161
): Promise {
11561162
let attrs;
11571163
let options;
@@ -1200,7 +1206,7 @@ class ParseObject {
12001206
saveOptions.sessionToken = options.sessionToken;
12011207
}
12021208
const controller = CoreManager.getObjectController();
1203-
const unsaved = unsavedChildren(this);
1209+
const unsaved = options.cascadeSave !== false ? unsavedChildren(this) : null;
12041210
return controller.save(unsaved, saveOptions).then(() => {
12051211
return controller.save(this, saveOptions);
12061212
});

0 commit comments

Comments
 (0)