1. Cloud Code Tips & Tricks
Parse London Meetup - December 4, 2013
Héctor Ramos
@hectorramos
2. Cloud Code Tips & Tricks
• Validating data when objects are saved.
• Performing arbitrary actions whenever objects are saved.
• Keeping client apps updated automatically in the background.
• Scheduling long running jobs.
3. Cloud Code Overview
• Hosted JavaScript environment.
• Access to all your Parse Data through the JavaScript SDK.
• Perform operations on a trusted environment.
• Cloud Code deployed with parse
• Hosting included.
deploy command.
5. Running Code Before Save
• Useful for cleaning up user-generated content.
• Validating required fields.
Business
Key
name
address
Value
“Facebook London”
“42 Earlham Street, London, WC2H 9LA”
6. Running Code Before Save
• Useful for cleaning up user-generated content.
• Validating required fields.
Business
Key
name
address
Business
Value
“TechOffice-FB-LON”
“42 Earlham Street, London, WC2H 9LA”
Key
name
address
Value
“Facebook London”
“42 Earlham Street, London, WC2H 9LA”
updatedAt
December 4, 2013 5:45 PM
createdAt
December 4, 2013 5:45 PM
7. Before Save 101
• Arbitrary code executed before an object is saved.
• Must finish within 3 seconds.
Parse.Cloud.beforeSave("Class Name", function(request, response) {
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
var objectBeingSaved = request.object;
var userSavingThisObjectIfAny = request.user;
if (someError) {
// Reject this update. Object will not be saved.
response.error(“SomeError occurred when saving this object.”);
} else {
// Proceed with saving the object with the suggested changes, if any.
response.success();
}
});
8. Parse.Cloud.beforeSave("Business", function(request, response) {
// object being saved: request.object
var businessName = request.object.get("name");
!
if (businessName === "TechOffice-FB-LON") {
!
// Use the new, clean name.
request.object.put("name", "Facebook London");
!
} else if (businessName === "TechOffice-FB-MPK") {
!
request.object.put("name", "Facebook Menlo Park");
!
}
!
// Proceed with saving the object with the suggested changes, if any.
response.success();
!
});
9. Parse.Cloud.beforeSave("Business", function(request, response) {
// object being saved: request.object
var businessName = request.object.get("name");
var businessAddress = request.object.get("address");
!
if (!businessName) {
response.error("Validation error: name is required.");
return;
}
!
if (!businessAddress) {
response.error("Validation error: address is required.");
return;
}
!
// ... code from previous slide
response.success();
!
});
10. Keeping Installations in Sync with Users
Helpful later on when sending targeted push notifications.
Parse.Cloud.beforeSave(Parse.Installation, function(request, response) {
!
if (request.user) {
request.object.set(“user”, request.user);
} else {
request.object.unset(“user”);
}
!
response.success();
!
});
11. Performing Actions After Save
• Sending push notifications to end users
• Silently updating client side data (iOS 7)
12. Push Notifications After Save
1. Push notifications sent when new comments are posted.
2. App should listen for incoming push notifications.
3. Show new content in-app automatically.
13. Push Notifications After Save
Push notifications sent when new comments are posted.
Parse.Cloud.afterSave("Comment", function(request) {
!
// 1. Get comment details.
!
// 2. Construct notification message.
!
// 3. Define our push notification audience.
!
// 4. Deliver push notification.
});
14. Parse.Cloud.afterSave("Comment", function(request) {
// 1. Get comment details.
var comment = request.object;
// New comment
var fromUser = request.user;
// User who is commenting on Post
var onPost = comment.get(“post”); // Post being commented on
var postOwner = onPost.get(“owner”); // Parse.User associated with Post
// 2. Construct notification message.
var message = fromUser.getUsername() + “: “ + comment.get(“content”);
var trimmedMessage = message.substr(0, 200);
!
// 3. Define our push notification audience.
var pushQuery = new Parse.Query(Parse.Installation);
pushQuery.where(“user”, postOwner);
// 4. Deliver push notification.
Parse.Push.send({
where: pushQuery,
data: {
alert: trimmedMessage, // Message to display in Push
postId: onPost.id
// Post id for client-side retrieval
}
});
});
15. Push Notifications After Save
Listening to incoming push notifications
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:
(NSDictionary *)launchOptions {
NSDictionary *pushPayload =
launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
!
}
// ...
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo {
// ...
!
}
Push Guide: Responding to the Payload
https://parse.com/docs/push_guide#receiving-responding
16. Push Notifications After Save
Showing in-app content automatically
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSString *postId = userInfo[@“postId"];
if (postId) {
// This is a push notification for an activity over a Post object
PFObject *post = [PFObject objectWithoutDataWithClassName:@"Post"
objectId:postId];
!
// Fetch the full Post object from Parse…
[post fetchInBackgroundWithBlock:^(PFObject *post, NSError *error) {
!
}
}
// …then we display this Post with any new data in the iPhone app.
PostsViewController *postsViewController = [PostsViewController new];
postsViewController.post = post;
[self.navigationController presentViewController:postsViewController
animated:YES completion:nil];
}];
17. Silently Updating Clients After Save
As of iOS 7, it’s possible to trigger background refresh remotely.
Parse.Cloud.afterSave("News", function(request) {
!
var pushQuery = new Parse.Query(Parse.Installation);
pushQuery.where("deviceType", "ios");
Parse.Push.send({
where: pushQuery,
data: {
content-available: 1
}
});
});
19. Background Job 101
• Long running operations, up to 15 minutes.
• Can be run on a schedule.
Parse.Cloud.job("jobName", function(request, status) {
var params = request.params;
!
status.message(“I’m running!”);
!
if (someErrorHappened) {
status.error(“The job ran into someError.”);
} else {
status.success(“The job finished successfully.”);
}
!
});
20. Jobs can be configured to run on a schedule
or on-demand with “Run Now”
Job status can be tracked through your Dashboard
21. Parse.Cloud.job("cleanupBusinessNames", function(request, status) {
var Business = Parse.Object.extend(“Business”);
var counter = 0;
!
var query = new Parse.Query(Business);
query.each().then(function(object) {
if (object.get(“name”) === “TechOffice-FB-LON”) {
object.set(“name”, “Facebook London”);
}
!
if (counter % 100 === 0) {
// Set the job's progress status every 100 loops.
status.message(counter + " businesses processed.");
}
counter += 1;
return object.save();
}).then(function() {
status.success("Done.");
}, function(error) {
status.error("Failed to update all objects.");
});
});