My Email object (my own custom class) is being written though the relation is not being set on time, any ideas how to chain this properly?
// Create new Email model and friend it
addFriendOnEnter: function(e) {
var self = this;
if (e.keyCode != 13) return;
var email = this.emails.create({
email: this.emailInput.val(),
ACL: new Parse.ACL(Parse.User.current())
});
var user = Parse.User.current();
var relation = user.relation("friend");
relation.add(email);
user.save();
this.emailInput.val('');
}
Thanks!
Gon
Because talking to Parse's servers is asynchronous, Parse.Collection.create uses a Backbone-style options object with a callback for when the object is created. I think what you want to do is:
// Create new Email model and friend it
addFriendOnEnter: function(e) {
var self = this;
if (e.keyCode != 13) return;
this.emails.create({
email: this.emailInput.val(),
ACL: new Parse.ACL(Parse.User.current())
}, {
success: function(email) {
var user = Parse.User.current();
var relation = user.relation("friend");
relation.add(email);
user.save();
self.emailInput.val('');
}
});
}
Got it!
The .create method on the this.emails collection does not actually return an object, so var email was empty. Somehow Parse guess it was an empty object of class Email, so I guess the structure is the only thing that remained once .create did its job.
Instead I retrieve the email object on the server using .query, .equalTo and .first
// Create new Email model and friend it
addFriendOnEnter: function(e) {
var self = this;
if (e.keyCode != 13) return;
this.emails.create({
email: this.emailInput.val(),
ACL: new Parse.ACL(Parse.User.current())
});
var query = new Parse.Query(Email);
query.equalTo("email", this.emailInput.val());
query.first({
success: function(result) {
alert("Successfully retrieved an email.");
var user = Parse.User.current();
var relation = user.relation("friend");
relation.add(result);
user.save();
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
this.emailInput.val('');
}
Related
I made two classes in parse User(by default) and UserData.
BeforeSave Trigger as follows:
Parse.Cloud.beforeSave(Parse.User, function(request, response) {
var userDataObject = new Parse.Object("UserData");
var fromUserPointer = {"__type":"Pointer","className":"_User","objectId":request.object.id};
return userDataObject.save({score: 0, ideasCount: 0, followersCount:0, return:0}).then(function (userData) {
var userDataPointer = {"__type":"Pointer","className":"UserData","objectId":userData.id};
request.object.set("userData", userDataPointer);
response.success();
}, function(error) {
response.error(error.message);
});
});
It saves user's UserData and takes its UserData pointer field and saves in UserData class.
Parse.Cloud.afterSave(Parse.User, function(request) {
Parse.Cloud.useMasterKey();
var userPointer = {"__type":"Pointer","className":"_User","objectId":request.object.id};
var userData = request.object.get("userData");
if (userData) {
var userDataPointer = {"__type":"Pointer","className":"UserData","objectId":userData.id};
var userDataQuery = new Parse.Query("UserData");
userData.set("user", userPointer);
return userData.save().then (function (userData) {
var activityObject = new Parse.Object("Activity");
return activityObject.save({fromUserData: userDataPointer, from:userPointer,
toUserData:userDataPointer, to:userPointer, type:"follow"});
}).then (function (success) {
}, function (error) {
console.error("Error in afterSave(user) : " + request.object.id + ":" + error.message);
});
}
});
The problem is that, before saving in the User class, it sometimes does not create UserData, which it should create. Hence these two triggers must run atomically, which they do not.
I have tried multiple variations of this and for some reason the field "Followers" is not being incremented:
ParseObject follow = new ParseObject("Follow");
follow.put("from", currentUser);
follow.put("to", parseUser);
follow.put("approved", approved);
Then in cloud code:
Parse.Cloud.afterSave("Follow", function(request) {
var to = request.object.get("to");
var query = new Parse.Query(Parse.User);
query.equalTo("objectId", to.id);
query.first({
success: function(user) {
user.increment("Followers");
user.save();
console.log("User: " + user.id + " Followers: " + user.get("Followers"));
}, error: function(error) {
console.log("afterSave: " + error);
}
});
var currentUser = Parse.User.current();
currentUser.increment("Following");
currentUser.save();
});
According to the logs it is working:
I2015-11-28T18:21:54.745Z]v47 after_save triggered for Follow for user k0ZvNAy3Mk:
Input: {"object":{"approved":false,"createdAt":"2015-11-28T18:21:54.743Z","from":{"__type":"Pointer","className":"_User","objectId":"k0ZvNAy3Mk"},"objectId":"JQBO9m21uA","to":{"__type":"Pointer","className":"_User","objectId":"bcpbFaXj9C"},"updatedAt":"2015-11-28T18:21:54.743Z"}}
Result: Success
I2015-11-28T18:21:54.906Z]User: bcpbFaXj9C Followers: 1
But when I look at the data the Followers field for that user still says 0
I have also tried:
Parse.Cloud.afterSave("Follow", function(request) {
var to = request.object.get("to");
to.increment("Followers");
to.save();
var currentUser = Parse.User.current();
currentUser.increment("Following");
currentUser.save();
});
According to the docs since it is a pointer I should be able to manipulate it directly but that did not work either.
Any ideas what to do or why this is not working correctly?
save() is asynchronous function, you should not leave the function before it is completed. Use this:
user.save().then(function(success){
console.log("User: " + success.id + " Followers: " + success.get("Followers"));
}, function (error){
console.log(error.message);
});
Looks like the parse cloud code depends on the user that is currently logged in and manipulating data on another user is not allowed unless you are logged in as them.
Parse.Cloud.afterSave("Follow", function(request) {
Parse.Cloud.useMasterKey(); // Needed this
var to = request.object.get("to");
to.increment("Followers");
to.save();
var currentUser = Parse.User.current();
currentUser.increment("Following");
currentUser.save();
});
Find my code below which working very fine. but only problem facing by me is that save event is not working for me.Also you can see my log file in the picture. In each method i tried success and error function which working fine as you can see in picture. I tried this code alot but still... it is not working for me.
It always shows error message.
Code :
Parse.Cloud.afterSave("HouserDetailed", function(request, response)
{
var obj = request.object.id;
//console.log(obj);
// code !
var houserdetailed = new Parse.Object("HouserDetailed");
var query = new Parse.Query("HouserDetailed");
query.equalTo("objectId", obj);
query.first({
success: function(results) {
//alert("updates objectId " +request.object.id + " " + "input" + " "+ request.object.bet_title );
var bet_title = results.get("bet_title");
var match_id = results.get("match_id");
var level_coin = results.get("level_coin");
if(bet_title !== "false")
{
console.log("bet_title :- "+bet_title+", match_id:- "+match_id+", level_coin:- "+level_coin);
// nested query
var better = new Parse.Object("Better");
var query1 = new Parse.Query("Better");
query1.equalTo("match_id", match_id);
query1.first({
success: function(result){
var bet_title_better = result.get("bet_title");
var user_id = result.get("user_id");
var bet_OnNoOfticket = result.get("bet_OnNoOfticket");
var bet_price = result.get("bet_price");
var money_got = bet_OnNoOfticket * bet_price;
console.log("bet_title_better :-"+bet_title_better);
if(bet_title !== bet_title_better)
{
console.log("Condition does not match!");
}
else
{
console.log("Condition match!" + "money got :- "+money_got);
// checking for existing user in parse DB
var wallet = new Parse.Object("Wallet");
var query2 = new Parse.Query("Wallet");
query2.equalTo("user_id", user_id);
query2.first({
success: function(result)
{
console.log("User found");
var wallet_coins_number = result.get("wallet_coins_number");
var objectId = result.get("objectId");
total_amount = +wallet_coins_number + +money_got;
console.log("Total amount got :- " + total_amount );
// saving amount in wallet
var Wallet = Parse.Object.extend("Wallet");
var wallet = new Wallet();
wallet.set("user_id", user_id);
wallet.set("wallet_coins_number", total_amount);
wallet.save(null, {
success: function(wallet){
console.log("amount saved in wallet!");
},
error: function(wallet)
{
console.log("amount not saved in wallet!");
}
});
},
error: function(error)
{
console.log("User not found");
}
});
}
},error: function(error)
{
}
});
}
// nested query end
},
error: function(error) {
console.log("Error: " + error.code + " " + error.message);
}
});
// code !
});][1]][1]
I don't see any log, probably it would tell you what is wrong. But you are attempting to save existing ParseObject with dirty objectId, which is bad idea. You are not allowed to change objectId of existing object. Try to remove wallet.set("objectId", objectId) from your code.
You should not use result.get("objectId") either, use result.id instead.
I'm attempting to create my first Parse Cloud Code function and am running into an issue:
Parse.Cloud.afterSave("Message", function(request) {
var fromUser = request.object.get("fromUser");
var toUser = request.object.get("toUser");
console.log(fromUser); // user pointer
console.log(toUser); // user pointer
});
As you can see both fromUser and toUser is a pointer when what I actually want is the user objects themselves. What is the best way to do this?
You can create a new query to get user informations.
var query = new Parse.Query(Parse.User);
query.get(request.object.get('fromUser').id, {
success: function(user) {
// What you want with user informations
},
error: function() {}
});
You can try this, but I've never try.
var query = new Parse.Query(Parse.User);
query.equalTo('objectId', request.object.get('fromUser').id);
query.equalTo('objectId', request.object.get('toUser').id);
query.find({
success: function(users) {
// What you want with users information
},
error: function() {}
});
I am too late, but I hope this will work
you can use
Parse.Cloud.beforeSave("Message", function(request, response) { ....
or
Parse.Cloud.afterSave("Message", function(request) { ....
.
this is how to use beforeSave
Parse.Cloud.beforeSave("Message", function(request, response) {
var message = request.object;
var fromUser = message.get("fromUser"); // you must have this User object, if it's null, then the object is null in the table
var toUser = message.get("toUser");
// fromUser and toUser columns must be Pointer<User> and have values
}).catch(function(error) {
response.error("Error finding message " + error.code + ": " + error.message);
});
});
I'm saving some objects into tables on my Parse Data. But I need to add a constraint or make sure that the data i'm trying to insert is unique. I'm using something like the following code. But i want to guarantee that the eventId (that I'm getting from facebook API) is unique in my tables, so i don't have any redundant information. What is the best way to make it work?
var Event = Parse.Object.extend("Event");
var event = new Event();
event.set("eventId", id);
event.set("eventName", name);
event.save(null, {
success: function(event) {
console.log('New object created with objectId: ' + event.eventId);
},
error: function(event, error) {
console.log('Failed to create new object, with error code: ' + error.message);
}
});
Update:
I'm calling it inside a httpRequest. The following is pretty much what I have and I cant figure out just how to call a beforeSave inside it.
Parse.Cloud.define("hello", function(request, response) {
var query = new Parse.Query("Location");
query.find({
success: function(results) {
console.log(results);
var totalResults = results.length;
var completedResults = 0;
var completion = function() {
response.success("Finished");
};
for (var i = 0; i < totalResults; ++i){
locationId = results[i].get("locationFbId");
Parse.Cloud.httpRequest({
url: 'https://graph.facebook.com/v2.2/'+locationId+'/events?access_token='+accessToken,
success: function(httpResponse) {
console.log(httpResponse.data);
console.log("dsa"+locationId);
for (var key in httpResponse.data) {
var obj = httpResponse.data[key];
for (var prop in obj) {
var eventObj = obj[prop];
if (typeof(eventObj) === 'object' && eventObj.hasOwnProperty("id")) {
var FbEvent = Parse.Object.extend("FbEvent");
var fbEvent = new FbEvent();
fbEvent.set("startDate",eventObj["start_time"]);
fbEvent.set("locationFbId", locationId);
fbEvent.set("fbEventId", eventObj["id"]);
fbEvent.set("fbEventName", eventObj["name"]);
Parse.Cloud.beforeSave("FbEvent", function(request, response) {
var query = new Parse.Query("FbEvent");
query.equalTo("fbEventId", request.params.fbEventId);
query.count({
success: function(number) {
if(number>0){
response.error("Event not unique");
} else {
response.success();
}
},
error: function(error) {
response.error(error);
}
});
});
}
}
}
completedResults++;
if (completedResults == totalResults) {
completion();
}
},
error:function(httpResponse){
completedResults++;
if (completedResults == totalResults)
response.error("Failed to login");
}
});
}
},
error: function() {
response.error("Failed on getting locationId");
}
});
});
So this is occurring in Cloud Code correct? (Im assuming since this is Javascript)
What you could do is create a function that occurs before each "Event" object is saved and run a query to make sure that the event is unique (query based off of "eventId" key, not objectId since the id comes from Facebook). If the event is unique, return response.success(), otherwise return response.error("Event not unique")
EX:
Parse.Cloud.beforeSave("Event", function(request, response) {
if(request.object.dirty("eventId")){
var query = var new Parse.Query("Event");
query.equalTo("eventId", request.object.eventId);
query.count({
success: function(number) {
if(number>0){
response.error("Event not unique");
} else {
response.success();
}
},
error: function(error) {
response.error(error);
}
});
} else {
response.success();
}
});
Parse.Cloud.define("hello", function(request, response) {
var query = new Parse.Query("Location");
query.find({
success: function(results) {
console.log(results);
var totalResults = results.length;
var completedResults = 0;
var completion = function() {
response.success("Finished");
};
for (var i = 0; i < totalResults; ++i){
locationId = results[i].get("locationFbId");
Parse.Cloud.httpRequest({
url: 'https://graph.facebook.com/v2.2/'+locationId+'/events?access_token='+accessToken,
success: function(httpResponse) {
console.log(httpResponse.data);
console.log("dsa"+locationId);
for (var key in httpResponse.data) {
var obj = httpResponse.data[key];
for (var prop in obj) {
var eventObj = obj[prop];
if (typeof(eventObj) === 'object' && eventObj.hasOwnProperty("id")) {
var FbEvent = Parse.Object.extend("FbEvent");
var fbEvent = new FbEvent();
fbEvent.set("startDate",eventObj["start_time"]);
fbEvent.set("locationFbId", locationId);
fbEvent.set("fbEventId", eventObj["id"]);
fbEvent.set("fbEventName", eventObj["name"]);
// Our beforeSave function is automatically called here when we save it (this will happen every time we save, so we could even upgrade our method as shown in its definition above)
fbEvent.save(null, {
success: function(event) {
console.log('New object created with objectId: ' + event.eventId);
},
error: function(event, error) {
console.log('Failed to create new object, with error code: ' + error.message);
}
});
}
}
}
completedResults++;
if (completedResults == totalResults) {
completion();
}
},
error:function(httpResponse){
completedResults++;
if (completedResults == totalResults)
response.error("Failed to login");
}
});
}
},
error: function() {
response.error("Failed on getting locationId");
}
});
});
This can also be accomplished before ever calling the save by querying and only saving if the query returns with a number == 0.
Summary: For those joining later, what we are doing here is checking to see if an object is unique (this time based on key eventId, but we could use any key) by overriding Parse's beforeSave function. This does mean that when we save our objects (for the first time) we need to be extra sure we have logic to handle the error that the object is not unique. Otherwise this could break the user experience (you should have error handling that doesn't break the user experience anyway though).