Skip to content

Commit

Permalink
Support fetchAllIfNeededWithInclude (#900)
Browse files Browse the repository at this point in the history
  • Loading branch information
dplewis authored Aug 23, 2019
1 parent f9a397b commit ae5d64a
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 12 deletions.
31 changes: 31 additions & 0 deletions integration/test/ParseObjectTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -1448,6 +1448,37 @@ describe('Parse Object', () => {
}).catch(done.fail);
});

it('can fetchAllIfNeededWithInclude', async () => {
const pointer = new TestObject({ foo: 'bar' });
const item1 = new Item({ x: 1});
const item2 = new Item({ x: 2, pointer });
const items = [item1, item2];

await Parse.Object.saveAll(items);

const container = new Container();
container.set('items', items);
await container.save();

const query = new Parse.Query(Container);
const containerAgain = await query.get(container.id);

// Fetch objects with no data
const itemsAgain = containerAgain.get('items');
const item1Again = itemsAgain[0].set('x', 100);
const item2Again = itemsAgain[1];

// Override item1 in database, this shouldn't fetch
await item1Again.save();

const fetchedItems = await Parse.Object.fetchAllIfNeededWithInclude([item1, item2Again], ['pointer']);
assert.equal(fetchedItems.length, items.length);
assert.equal(fetchedItems[0].get('x'), 1);
assert.equal(fetchedItems[1].get('x'), 2); // item2Again should update
assert.equal(fetchedItems[1].get('pointer').id, pointer.id);
assert.equal(fetchedItems[1].get('pointer').get('foo'), 'bar');
});

it('can fetchAllIfNeeded', (done) => {
const numItems = 11;
const container = new Container();
Expand Down
67 changes: 55 additions & 12 deletions src/ParseObject.js
Original file line number Diff line number Diff line change
Expand Up @@ -1427,18 +1427,7 @@ class ParseObject {
queryOptions.sessionToken = options.sessionToken;
}
if (options.hasOwnProperty('include')) {
queryOptions.include = [];
if (Array.isArray(options.include)) {
options.include.forEach((key) => {
if (Array.isArray(key)) {
queryOptions.include = queryOptions.include.concat(key);
} else {
queryOptions.include.push(key);
}
});
} else {
queryOptions.include.push(options.include);
}
queryOptions.include = ParseObject.handleIncludeOptions(options);
}
return CoreManager.getObjectController().fetch(
list,
Expand Down Expand Up @@ -1481,6 +1470,41 @@ class ParseObject {
return ParseObject.fetchAll(list, options);
}

/**
* Fetches the given list of Parse.Object if needed.
* If any error is encountered, stops and calls the error handler.
*
* Includes nested Parse.Objects for the provided key. You can use dot
* notation to specify which fields in the included object are also fetched.
*
* If any error is encountered, stops and calls the error handler.
*
* <pre>
* Parse.Object.fetchAllIfNeededWithInclude([object1, object2, ...], [pointer1, pointer2, ...])
* .then((list) => {
* // All the objects were fetched.
* }, (error) => {
* // An error occurred while fetching one of the objects.
* });
* </pre>
*
* @param {Array} list A list of <code>Parse.Object</code>.
* @param {String|Array<string|Array<string>>} keys The name(s) of the key(s) to include.
* @param {Object} options
* Valid options are:<ul>
* <li>useMasterKey: In Cloud Code and Node only, causes the Master Key to
* be used for this request.
* <li>sessionToken: A valid session token, used for making a request on
* behalf of a specific user.
* </ul>
* @static
*/
static fetchAllIfNeededWithInclude(list: Array<ParseObject>, keys: String|Array<string|Array<string>>, options: RequestOptions) {
options = options || {};
options.include = keys;
return ParseObject.fetchAllIfNeeded(list, options);
}

/**
* Fetches the given list of Parse.Object if needed.
* If any error is encountered, stops and calls the error handler.
Expand Down Expand Up @@ -1508,13 +1532,32 @@ class ParseObject {
if (options.hasOwnProperty('sessionToken')) {
queryOptions.sessionToken = options.sessionToken;
}
if (options.hasOwnProperty('include')) {
queryOptions.include = ParseObject.handleIncludeOptions(options);
}
return CoreManager.getObjectController().fetch(
list,
false,
queryOptions
);
}

static handleIncludeOptions(options) {
let include = [];
if (Array.isArray(options.include)) {
options.include.forEach((key) => {
if (Array.isArray(key)) {
include = include.concat(key);
} else {
include.push(key);
}
});
} else {
include.push(options.include);
}
return include;
}

/**
* Destroy the given list of models on the server if it was already persisted.
*
Expand Down

0 comments on commit ae5d64a

Please sign in to comment.