Skip to content

Commit

Permalink
Improve support for nested keys (#1364)
Browse files Browse the repository at this point in the history
* Better support for nested keys

* Added a test for nested fields
Bugfix on ObjectStateMutations patch

* Move the new test under integration/

* Modified an existing test
  ParseUser.get('password') used to return undefined, now password is not an attribute

* Use curly braces
  • Loading branch information
mstniy committed May 14, 2021
1 parent 86c05ad commit ffc523f
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 3 deletions.
14 changes: 14 additions & 0 deletions integration/test/ParseObjectTest.js
Expand Up @@ -401,6 +401,20 @@ describe('Parse Object', () => {
assert.equal(result.get('objectField').number, 20);
});

it('can set non existing nested fields to objects', async () => {
const o = new Parse.Object('Person');
expect(o.attributes).toEqual({});
o.set('data', {});
await o.save();
expect(o.get('data')).toEqual({});
o.set('data.a', {});
await o.save();
expect(o.get('data')).toEqual({ a: {} });
o.set('data.a.b', {});
await o.save();
expect(o.get('data')).toEqual({ a: { b: {} } });
});

it('can set non existing fields', async () => {
const obj = new TestObject();
obj.set('objectField', { number: 5 });
Expand Down
2 changes: 1 addition & 1 deletion integration/test/ParseUserTest.js
Expand Up @@ -505,7 +505,7 @@ describe('Parse User', () => {
return user.save();
})
.then(() => {
assert.equal(Object.keys(user.attributes).length, 6);
assert.equal(Object.keys(user.attributes).length, 5);
assert(user.attributes.hasOwnProperty('username'));
assert(user.attributes.hasOwnProperty('email'));
return user.destroy();
Expand Down
15 changes: 14 additions & 1 deletion src/ObjectStateMutations.js
Expand Up @@ -154,14 +154,27 @@ export function estimateAttributes(
return data;
}

function nestedSet(obj, key, value) {
const path = key.split('.');
for (let i = 0; i < path.length - 1; i++) {
if (!(path[i] in obj)) obj[path[i]] = {};
obj = obj[path[i]];
}
if (typeof value === 'undefined') {
delete obj[path[path.length - 1]];
} else {
obj[path[path.length - 1]] = value;
}
}

export function commitServerChanges(
serverData: AttributeMap,
objectCache: ObjectCache,
changes: AttributeMap
) {
for (const attr in changes) {
const val = changes[attr];
serverData[attr] = val;
nestedSet(serverData, attr, val);
if (
val &&
typeof val === 'object' &&
Expand Down
2 changes: 1 addition & 1 deletion src/ParseObject.js
Expand Up @@ -409,7 +409,7 @@ class ParseObject {
for (attr in pending) {
if (pending[attr] instanceof RelationOp) {
changes[attr] = pending[attr].applyTo(undefined, this, attr);
} else if (!(attr in response) && !attr.includes('.')) {
} else if (!(attr in response)) {
// Only SetOps and UnsetOps should not come back with results
changes[attr] = pending[attr].applyTo(undefined);
}
Expand Down

0 comments on commit ffc523f

Please sign in to comment.