Parse London Meetup - Cloud Code Tips & Tricks

Preview:

DESCRIPTION

December 4, 2013 presentation on Cloud Code.

Citation preview

Héctor Ramos@hectorramos

Cloud Code Tips & TricksParse London Meetup - December 4, 2013

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.

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 deploy command.

• Hosting included.

Cloud Code Overview

Save Hooks Hosting

Background Jobs Cloud Modules

Functions

Webhooks

Running Code Before Save• Useful for cleaning up user-generated content.

• Validating required fields.

Key Valuename “Facebook London”

address “42 Earlham Street, London, WC2H 9LA”

Business

Running Code Before Save• Useful for cleaning up user-generated content.

• Validating required fields.

Key Valuename “TechOffice-FB-LON”

address “42 Earlham Street, London, WC2H 9LA”

Key Valuename “Facebook London”

address “42 Earlham Street, London, WC2H 9LA”

updatedAt December 4, 2013 5:45 PM

createdAt December 4, 2013 5:45 PM

Business Business

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(); }

Before Save 101• Arbitrary code executed before an object is saved.

• Must finish within 3 seconds.

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(); !});

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(); !});

Parse.Cloud.beforeSave(Parse.Installation, function(request, response) { ! if (request.user) { request.object.set(“user”, request.user); } else { request.object.unset(“user”); } ! response.success(); !});

Keeping Installations in Sync with UsersHelpful later on when sending targeted push notifications.

Performing Actions After Save• Sending push notifications to end users

• Silently updating client side data (iOS 7)

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.

Push Notifications After Save

Parse.Cloud.afterSave("Comment", function(request) { ! // 1. Get comment details. ! // 2. Construct notification message. ! // 3. Define our push notification audience. ! // 4. Deliver push notification. });

Push notifications sent when new comments are posted.

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 } }); });

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSDictionary *pushPayload = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]; ! // ... }

Push Guide: Responding to the Payload https://parse.com/docs/push_guide#receiving-responding

Listening to incoming push notificationsPush Notifications After Save

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { // ... !}

- (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]; }]; } }

Showing in-app content automaticallyPush Notifications After Save

Silently Updating Clients After Save

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 } }); });

As of iOS 7, it’s possible to trigger background refresh remotely.

Updating Query Cache

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { ! PFQuery *query = [PFQuery queryWithClassName:@"News"]; query.cachePolicy = kPFCachePolicyNetworkOnly; [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) { if (!error) { completionHandler(UIBackgroundFetchResultNewData); } else { completionHandler(UIBackgroundFetchResultFailed); } }]; }

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.”); } !});

Background Job 101• Long running operations, up to 15 minutes.

• Can be run on a schedule.

Jobs can be configured to run on a schedule

Job status can be tracked through your Dashboard

or on-demand with “Run Now”

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."); }); });

Q & A

Recommended