Search code examples
parse-platformparse-cloud-codeparse-javascript-sdk

PARSE check original object on BeforeSave


I need to check the original object on before save to see what value has changed. currently i have this:

Parse.Cloud.beforeSave("Stats", function(request, response) {
if (!request.object.isNew()){
        var query = new Parse.Query("Stats");
        query.get(request.object.id, { 
            success: function(oldObject) {
            alert('OLD:' + oldObject.get("Score") + "new:" + request.object.get("Score"));
                /*Do My Stuff Here*/
                response.success(); 
            },
            error: function(oldObject, error) {
                response.error(error.message);
            }
        });
    }else{
        response.success();
    }

});

The problem is that oldObject is equal to request.object.

Also the alert result is this: OLD:10 new:10, but the real old score was 5. Also according to the before save input log the original is really 5.

Any ideia what i am doing wrong?

Edit: Here is the before save log.

before_save triggered for Stats as master:
Input: {"original":{"achievements":[],"Score":"100"updatedAt":"2015-11-02T10:09:24.170Z"},"update":{"Score":"110"}}
Result: Update changed to {"Score":"110"}

Edit2: Is there any way to get the dirty value?

console.log("dirty: "+ request.object.dirty("score"));
I2015-11-03T14:23:12.198Z]dirty: true

Solution

  • The official way to know if a field was modified is to call dirty().

    My guess is that querying for that particular object somehow updates all "instances" of that object in the current scope, and that's way dirty() works only if called before the query.

    An option to get both the old and the new value is to mantain it in a separate field. For example, from your client you could call (pseudocoding, but you get the point):

    // OldScore here is 0
    statObject.put("Score") = 100;
    statObject.saveInBackground();
    

    Then in Cloud Code:

    Parse.Cloud.beforeSave("Stats", function(request, response) {
    
        var stat = request.object;
        if (!stat.isNew()){
            if (stat.dirty("Score")) {
                var newValue = stat.get("Score") // 100
                var oldValue = stat.get("OldScore") // 0
    
                // Do other stuff here
    
                stat.put("OldScore", newValue);
                response.success();
    
            } else {
                response.success();
            }
        } else {
            response.success();
        }
    });
    

    However the issue you are describing is somewhat strange. Maybe you could try with the fetch() command; it should return the old value. However it will invalidate every other dirty field.