Skip to content

Commit

Permalink
Merge pull request #619 from ParsePlatform/nlutsenko.triggers.inflate
Browse files Browse the repository at this point in the history
Improve beforeSave triggers for newly created objects.
  • Loading branch information
nlutsenko committed Feb 24, 2016
2 parents 1ae61c9 + ae82f33 commit a41ca28
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 12 deletions.
42 changes: 42 additions & 0 deletions spec/ParseAPI.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,48 @@ describe('miscellaneous', function() {
done();
});
});

it('pointer mutation properly saves object', done => {
let className = 'GameScore';

Parse.Cloud.beforeSave(className, (req, res) => {
let object = req.object;
expect(object instanceof Parse.Object).toBeTruthy();

let child = object.get('child');
expect(child instanceof Parse.Object).toBeTruthy();
child.set('a', 'b');
child.save().then(() => {
res.success();
});
});

let obj = new Parse.Object(className);
obj.set('foo', 'bar');

let child = new Parse.Object('Child');
child.save().then(() => {
obj.set('child', child);
return obj.save();
}).then(() => {
let query = new Parse.Query(className);
query.include('child');
return query.get(obj.id).then(objAgain => {
expect(objAgain.get('foo')).toEqual('bar');

let childAgain = objAgain.get('child');
expect(childAgain instanceof Parse.Object).toBeTruthy();
expect(childAgain.get('a')).toEqual('b');

return Promise.resolve();
});
}).then(() => {
done();
}, error => {
fail(error);
done();
});
});
});

it('test afterSave get full object on create and update', function(done) {
Expand Down
14 changes: 7 additions & 7 deletions src/RestWrite.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,24 +111,24 @@ RestWrite.prototype.validateSchema = function() {
// Runs any beforeSave triggers against this operation.
// Any change leads to our data being mutated.
RestWrite.prototype.runBeforeTrigger = function() {
// Avoid doing any setup for triggers if there is no 'beforeSave' trigger for this class.
if (!triggers.triggerExists(this.className, triggers.Types.beforeSave)) {
return Promise.resolve();
}

// Cloud code gets a bit of extra data for its objects
var extraData = {className: this.className};
if (this.query && this.query.objectId) {
extraData.objectId = this.query.objectId;
}

let originalObject = null;
let updatedObject = null;
let updatedObject = triggers.inflate(extraData, this.originalData);
if (this.query && this.query.objectId) {
// This is an update for existing object.
originalObject = triggers.inflate(extraData, this.originalData);
updatedObject = triggers.inflate(extraData, this.originalData);
updatedObject.set(Parse._decode(undefined, this.data));
} else {
// This is create of an object, so no original object exists.
// TODO: (nlutsenko) Use the same flow as for creation, when _Session triggers support is removed.
updatedObject = triggers.inflate(extraData, this.data);
}
updatedObject.set(Parse._decode(undefined, this.data));

return Promise.resolve().then(() => {
return triggers.maybeRunTrigger(
Expand Down
19 changes: 15 additions & 4 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,24 +211,35 @@ function addParseCloud() {
afterDelete: {}
};

function validateClassNameForTriggers(className) {
const restrictedClassNames = [ '_Session' ];
if (restrictedClassNames.indexOf(className) != -1) {
throw `Triggers are not supported for ${className} class.`;
}
}

Parse.Cloud.define = function(functionName, handler, validationHandler) {
Parse.Cloud.Functions[functionName] = handler;
Parse.Cloud.Validators[functionName] = validationHandler;
};
Parse.Cloud.beforeSave = function(parseClass, handler) {
var className = getClassName(parseClass);
let className = getClassName(parseClass);
validateClassNameForTriggers(className);
Parse.Cloud.Triggers.beforeSave[className] = handler;
};
Parse.Cloud.beforeDelete = function(parseClass, handler) {
var className = getClassName(parseClass);
let className = getClassName(parseClass);
validateClassNameForTriggers(className);
Parse.Cloud.Triggers.beforeDelete[className] = handler;
};
Parse.Cloud.afterSave = function(parseClass, handler) {
var className = getClassName(parseClass);
let className = getClassName(parseClass);
validateClassNameForTriggers(className);
Parse.Cloud.Triggers.afterSave[className] = handler;
};
Parse.Cloud.afterDelete = function(parseClass, handler) {
var className = getClassName(parseClass);
let className = getClassName(parseClass);
validateClassNameForTriggers(className);
Parse.Cloud.Triggers.afterDelete[className] = handler;
};
Parse.Cloud.httpRequest = httpRequest;
Expand Down
7 changes: 6 additions & 1 deletion src/triggers.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ var getTrigger = function(className, triggerType) {
return undefined;
};

function triggerExists(className: string, type: string): boolean {
return (getTrigger(className, type) != undefined);
}

var getRequestObject = function(triggerType, auth, parseObject, originalParseObject) {
var request = {
triggerName: triggerType,
Expand Down Expand Up @@ -52,7 +56,7 @@ var getResponseObject = function(request, resolve, reject) {
success: function() {
var response = {};
if (request.triggerName === Types.beforeSave) {
response['object'] = request.object.toJSON();
response['object'] = request.object._getSaveJSON();
}
return resolve(response);
},
Expand Down Expand Up @@ -96,5 +100,6 @@ module.exports = {
getRequestObject: getRequestObject,
inflate: inflate,
maybeRunTrigger: maybeRunTrigger,
triggerExists: triggerExists,
Types: Types
};

0 comments on commit a41ca28

Please sign in to comment.