0

I am trying to send a Push Notification through Parse Cloud Code when a certain object has been modified - "dirty"

I think I am almost there, but received an error because I believe am creating a new user instead of querying for one.

Parse.Cloud.beforeSave("Fact", function(request, response) {
  var dirtyKeys = request.object.dirtyKeys();
  for (var i = 0; i < dirtyKeys.length; ++i) {
    var dirtyKey = dirtyKeys[i];
    if (dirtyKey === "isValid") {

      //send push
      // Creates a pointer to _User with object id of userId

      var targetUser = new Parse.User();
      // targetUser.id = userId;
      targetUser.id = request.object.userID;

      var query = new Parse.Query(Parse.Installation);
      query.equalTo('user', targetUser);

      Parse.Push.send({
        where: query,
        data: {
          alert: "Your Fact was approved :)"
        }
      });

      return;
    }
  }
  response.success();
});

I found this post related to my problem. My question now is how to integrate the user query in my beforeSave block. Ideally I would create another function for the user query and place that in my beforeSave block.

**5/14 Update I took @toddg's advice and fixed the before save. Here is a clearer picture of what I am trying to do and the new error.

Updating of the entry error

Community
  • 1
  • 1
mparrish91
  • 101
  • 3
  • 11
  • It's better to put notification code in after save block. In the code above response.success() might run before sending push notification. Also the return; prevents it from notifying response.success() or response.error(). I recommend moving notification stuffs to afterSave – Subash May 12 '16 at 17:58
  • What's the error you're getting by the way? – toddg May 12 '16 at 19:54
  • I was getting this error - "Cannot create a pointer to an unsaved ParseObject" – mparrish91 May 13 '16 at 17:37

1 Answers1

0

A couple points (as @Subash noted in the comments) before I get into the code:

  1. Parse.Push.send is an async operation, so you'll want to ensure you call response.success() after your push send completes. I'm going to deal with this using Promises, as I think they are more flexible than callbacks. If you're not familiar, read about them here
  2. The return in your if statement will likely prevent the response.success() from being called.

Here's my recommended way of doing it:

Parse.Cloud.beforeSave("Fact", function(request, response) {

  // Keep track of whether we need to send the push notification
  var shouldPushBeSent = false;

  var dirtyKeys = request.object.dirtyKeys();
  for (var i = 0; i < dirtyKeys.length; ++i) {
    var dirtyKey = dirtyKeys[i];

    if (dirtyKey === "isValid") {
      shouldPushBeSent = true;
    }
  }

  if (shouldPushBeSent) {

      //send push
      // Creates a pointer to _User with object id of userId

      var targetUser = new Parse.User();
      // targetUser.id = userId;
      targetUser.id = request.object.userId;

      var query = new Parse.Query(Parse.Installation);

      // We want to pass the User object to the query rather than the UserId
      query.equalTo('user', targetUser);
      Parse.Push.send({
        where: query, // Set our Installation query
        data: {
          alert: "Your fact was approved"
        }
      }).then(function(){

        // Now we know the push notification was successfully sent
        response.success();
      }, function(error){

        // There was an error sending the push notification
        response.error("We had an error sending push: " + error);
      });
  } else {
    // We don't need to send the push notification.
    response.success();
  }
});

By the way, I'm assuming that you have a column on your Installation class that tracks which user is associated with each Installation.

toddg
  • 2,863
  • 2
  • 18
  • 33
  • Thank you for the prompt response! This looks great, going to implement it shortly. I do have an Installation class, but I don't have a userID column there. Is that what I would need to add? And then I would have to send that userId from the iOS app to Parse? – mparrish91 May 13 '16 at 17:36
  • for others who are trying to add a column to installation, very simple. here is how i did `let user = PFUser.currentUser() let currentInstallation = PFInstallation.currentInstallation() currentInstallation.setObject((user?.objectId!)!, forKey: "userID") currentInstallation.saveInBackground()` – mparrish91 May 15 '16 at 05:02