I have received some excellent information on Parse promises so far and am ready to soak up the next bit of the puzzle to me... relations of relations. The following code is in most part in answering Issues with Parse Cloud Code Promises but I have in the comments of the sections piece of code my next question. How would I go about further querying of relations within the top level relations? would be great to see how you would extend you code to do that @roamer-1888
Latest:
//Return a single project
Parse.Cloud.define('getProjectByUrl', function(request, response) {
var Projects = Parse.Object.extend("projects"); // with credit to @kRiZ
var query = new Parse.Query(Projects);
query.equalTo('projectUrl', request.params.projectUrl);
query.include("projectStatus"); // *MJ Added the include to add the project Status pointer
query.find().then(function(projectsResult) {
var project = projectsResult[0];
//From here, `project` is hierarchically monkey-patched with the results of further queries.
//Make tags query, the referees query and the sections query in parallel.
var tagsPromise = project.relation('tags').query().find();
var refereesPromise = project.relation('referees').query().find();
var sectionsPromise = project.relation('sections').query().include("sectionType").find(); //*MJ Added the include of the sectionType pointer
// Aggregate the three promises with Parse.Promise.when(), and handle the responses.
return Parse.Promise.when(tagsPromise, refereesPromise, sectionsPromise).then(function(tags, referees, sections) {
project.set('tags', tags);
project.set('referees', referees);
project.set('sections', sections);
//Go deeper into `sections`
var sectionsRelationsPromises = sections.map(function(section) {
// *MJ Remove sectionTypesPromise as it's a pointer
var filesPromise = section.relation('files').query().include("fileType").find(); // *MJ Added the include to grab the fileType pointer
return Parse.Promise.when(filesPromise).then(function(files) {
//*MJ Removed the promise for section Types
section.set('files', files);
// *MJ Removed the Deeper Logic
});
});
return Parse.Promise.when(sectionsRelationsPromises);
}).then(function() {
return project;
});
}).then(function(project) {
// At this point, all the data is gathered in the form of Parse objects in project,
// which now needs to be mapped into a js plain object.
var projectData = projectObj(project);
projectData.tags = project.get('tags').map(tagObj); //Process the tags response
projectData.referees = project.get('referees').map(refereeObj); // *MJ removed one e from refereeObj //Process the referees response
projectData.sections = project.get('sections').map(sectionObj); //Process the sections response
// *MJ Removed the adding of the files and looking over the sections.
//Yay! (hopfully)
response.success(projectData);
}).fail(function(error) {
response.error('Error: ' + error);
});
// ***********************************
// ***** start: mapper functions *****
// ***********************************
function projectObj(project) {
return { // *MJ Removed the stray equals sign here
'id': project.id,
'title': project.get('title'),
'previewImage': project.get('previewImage'),
'longDescription': project.get('longDescription'),
'shortDescription': project.get('shortDescription'),
'visibleToPublic': project.get('visibleToPublic'),
'dateStart': project.get('dateStart'),
'dateEnd': project.get('dateEnd'),
'updatedAt': project.get('updatedAt'),
"projectStatus": project.get("projectStatus").get("status") //*MJ Added the get of the Project Status status.
}
}
function tagObj(tag) {
return {
'tag': tag.get('tag')
};
}
function refereeObj(referee) {
return {
'name': referee.get('name'),
'role': referee.get('role'),
'emailAddress': referee.get('emailAddress'),
'phoneNumber': referee.get('phoneNumber'),
'linkedInUrl': referee.get('linkedInUrl')
};
}
function sectionObj(section) {
return {
'type': section.get('sectionType').get("type"), // *MJ Added the pointer for SectionType > type
'order': section.get('order'),
'content': section.get('content'),
'files': section.get('files').map(fileObj)
};
}
function fileObj(file) {
return {
'name': file.get('name'), // *MJ chnaged the name to be more appropriate
'url': file.get('url'), // *MJ Added the missing comma
'type': file.get('fileType').get("type") //*MJ Added the pointer for fileType > type and removed semi colon
};
}
// *********************************
// ***** fin: mapper functions *****
// *********************************
});
Old:
//Return a single project
Parse.Cloud.define('getProject', function(request, response) {
var Projects = Parse.Object.extend("projects"); // with credit to @kRiZ
var query = new Parse.Query(Projects);
query.equalTo('projectUrl', request.params.projectUrl);
query.find().then(function(projectsResult) {
var project = projectsResult[0];
var projectData = {
'id': project.id,
'title': project.get('title'),
'previewImage': project.get('previewImage'),
'longDescription': project.get('longDescription'),
'shortDescription': project.get('shortDescription'),
'visibleToPublic': project.get('visibleToPublic'),
'dateStart': project.get('dateStart'),
'dateEnd': project.get('dateEnd'),
'updatedAt': project.get('updatedAt')
};
//Now make the tags query and the referees query in parallel.
var tagsPromise = project.relation('tags').query().find();
var refereesPromise = project.relation('referees').query().find();
var sectionsPromise = project.relation('sections').query().find();
var sectionTypesPromise = project.relation('sections').query().find().relation('type').query().find();
var filesPromise = project.relation('sections').query().find().relation('files').query().find();
var fileTypesPromise = project.relation('sections').query().find().relation('files').query().find().relation('type').query().find();
// Aggregate the two promises with Parse.Promise.when(), and handle the responses.
return Parse.Promise.when(tagsPromise, refereesPromise, sectionsPromise, sectionTypesPromise, filesPromise, fileTypesPromise).then(function(tags, referees, sections, sectionTypes, files, fileTypes) {
//Process the tags response
projectData.tags = tags.map(function(tag) {
return {
'tag': tag.get('tag')
};
});
//Process the referees response
projectData.referees = referees.map(function(refereee) {
return {
'name': refereee.get('name'),
'role': refereee.get('role'),
'emailAddress': refereee.get('emailAddress'),
'phoneNumber': refereee.get('phoneNumber'),
'linkedInUrl': refereee.get('linkedInUrl')
};
});
//Process the sections response
projectData.sections = sections.map(function(section) {
return {
'order': section.get('order'),
'content': section.get('content')
};
});
// Problem: Sections have a relations column (files)
// which I would like to return as a child of sections.
// The files class then has a pointer column (type)
// to another class which contains the a list of
// file types (i.e. Image, Document, etc...)
// The sections structure of projectDate should
// look like:
//
// "sections": [{
// "type": "Section Type"
// "order": "1",
// "content": "This is the Section content",
// "files": [{
// "filename": "Image 1",
// "url": "image-1.png"
// "type": "Image"
// },
// {
// "filename": "Image 2",
// "url": "image-2.png",
// "type": "Image"
// },
// {
// ...
// }]
// },
// {
// ...
// }
// }]
//Process the section type response. This is reliant on sections being retrieved.
projectData.sections.type = sections.map(function(sectionTypes) {
return {
'type': sectionTypes.get('type')
};
});
//Process the section files response. This is reliant on sections being retrieved.
projectData.sections.files = sections.map(function(files) {
return {
'filename': files.get('filename'),
'url': files.get('url')
};
});
//Process the section files types response. This is reliant on files being retrieved.
projectData.sections.files.type = sections.map(function(fileTypes) {
return {
'type': fileTypes.get('type')
};
});
// Currently not so Yay!
response.success(projectData);
});
}).fail(function(error) {
response.error('Error: ' + error);
});
});