-
-
Notifications
You must be signed in to change notification settings - Fork 597
Support Fetch With Include #631
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -193,6 +193,55 @@ describe('Parse User', () => { | |
}); | ||
}); | ||
|
||
it('can fetch non-auth user with include', async () => { | ||
Parse.User.enableUnsafeCurrentUser(); | ||
|
||
const child = new Parse.Object('TestObject'); | ||
child.set('field', 'test'); | ||
let user = new Parse.User(); | ||
user.set('password', 'asdf'); | ||
user.set('email', '[email protected]'); | ||
user.set('username', 'zxcv'); | ||
user.set('child', child); | ||
await user.signUp(); | ||
|
||
const query = new Parse.Query(Parse.User); | ||
const userNotAuthed = await query.get(user.id); | ||
|
||
assert.equal(userNotAuthed.get('child').get('field'), undefined); | ||
|
||
const fetchedUser = await userNotAuthed.fetchWithInclude('child'); | ||
|
||
assert.equal(userNotAuthed.get('child').get('field'), 'test'); | ||
assert.equal(fetchedUser.get('child').get('field'), 'test'); | ||
}); | ||
|
||
it('can fetch auth user with include', async () => { | ||
Parse.User.enableUnsafeCurrentUser(); | ||
|
||
const child = new Parse.Object('TestObject'); | ||
child.set('field', 'test'); | ||
let user = new Parse.User(); | ||
user.set('password', 'asdf'); | ||
user.set('email', '[email protected]'); | ||
user.set('username', 'zxcv'); | ||
user.set('child', child); | ||
await user.signUp(); | ||
|
||
user = await Parse.User.logIn('zxcv', 'asdf'); | ||
|
||
assert.equal(user.get('child').get('field'), undefined); | ||
assert.equal(Parse.User.current().get('child').get('field'), undefined); | ||
|
||
const fetchedUser = await user.fetchWithInclude('child'); | ||
const current = await Parse.User.currentAsync(); | ||
|
||
assert.equal(user.get('child').get('field'), 'test'); | ||
assert.equal(current.get('child').get('field'), 'test'); | ||
assert.equal(fetchedUser.get('child').get('field'), 'test'); | ||
assert.equal(Parse.User.current().get('child').get('field'), 'test'); | ||
}); | ||
|
||
it('can store the current user', (done) => { | ||
Parse.User.enableUnsafeCurrentUser(); | ||
let user = new Parse.User(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -983,10 +983,48 @@ class ParseObject { | |
if (options.hasOwnProperty('sessionToken')) { | ||
fetchOptions.sessionToken = options.sessionToken; | ||
} | ||
if (options.hasOwnProperty('include')) { | ||
fetchOptions.include = []; | ||
if (Array.isArray(options.include)) { | ||
options.include.forEach((key) => { | ||
if (Array.isArray(key)) { | ||
fetchOptions.include = fetchOptions.include.concat(key); | ||
} else { | ||
fetchOptions.include.push(key); | ||
} | ||
}); | ||
} else { | ||
fetchOptions.include.push(options.include); | ||
} | ||
} | ||
var controller = CoreManager.getObjectController(); | ||
return controller.fetch(this, true, fetchOptions); | ||
} | ||
|
||
/** | ||
* Fetch the model from the server. If the server's representation of the | ||
* model differs from its current attributes, they will be overriden. | ||
* | ||
* Includes nested Parse.Objects for the provided key. You can use dot | ||
* notation to specify which fields in the included object are also fetched. | ||
* | ||
* @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> | ||
* @return {Promise} A promise that is fulfilled when the fetch | ||
* completes. | ||
*/ | ||
fetchWithInclude(keys: String|Array<string|Array<string>>, options: RequestOptions): Promise { | ||
options = options || {}; | ||
options.include = keys; | ||
return this.fetch(options); | ||
} | ||
|
||
/** | ||
* Set a hash of model attributes, and save the model to the server. | ||
* updatedAt will be updated when the request returns. | ||
|
@@ -1135,7 +1173,7 @@ class ParseObject { | |
* @param {Object} options | ||
* @static | ||
*/ | ||
static fetchAll(list: Array<ParseObject>, options) { | ||
static fetchAll(list: Array<ParseObject>, options: RequestOptions) { | ||
var options = options || {}; | ||
|
||
var queryOptions = {}; | ||
|
@@ -1145,13 +1183,55 @@ class ParseObject { | |
if (options.hasOwnProperty('sessionToken')) { | ||
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); | ||
} | ||
} | ||
return CoreManager.getObjectController().fetch( | ||
list, | ||
true, | ||
queryOptions | ||
); | ||
} | ||
|
||
/** | ||
* Fetches the given list of Parse.Object. | ||
* | ||
* 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.fetchAllWithInclude([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 | ||
* @static | ||
*/ | ||
static fetchAllWithInclude(list: Array<ParseObject>, keys: String|Array<string|Array<string>>, options: RequestOptions) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do we add more things like those warppers? semms un necessary if it's properly documented in the RequestOptions. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm sorry I'm not following. How should it be? I like shorthand but we could leave it like
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, that was my point, but we can keep the nice interfaces also, i don’t mind |
||
options = options || {}; | ||
options.include = keys; | ||
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. | ||
|
@@ -1570,6 +1650,9 @@ var DefaultController = { | |
} | ||
var query = new ParseQuery(className); | ||
query.containedIn('objectId', ids); | ||
if (options && options.include) { | ||
query.include(options.include); | ||
} | ||
query._limit = ids.length; | ||
return query.find(options).then((objects) => { | ||
var idMap = {}; | ||
|
@@ -1604,10 +1687,14 @@ var DefaultController = { | |
}); | ||
} else { | ||
var RESTController = CoreManager.getRESTController(); | ||
const params = {}; | ||
if (options && options.include) { | ||
params.include = options.include.join(); | ||
} | ||
return RESTController.request( | ||
'GET', | ||
'classes/' + target.className + '/' + target._getId(), | ||
{}, | ||
params, | ||
options | ||
).then((response, status, xhr) => { | ||
if (target instanceof ParseObject) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small nit: remove one space
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here. Sorry, forgot to hit ‘comment’ at the end of the review
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add eslint to this project at some point? It looks like it would be a lot of work tho :/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nobody will ever hate you for adding it.