Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialAaron Watkins
10,902 PointsParse.com + Swift: How do you add PFUser.currentUser() to another user's relations using Cloud Code & the Master Key?
Hi all,
I am creating a social networking app with the customary method of adding friends: User A: sends friend request to user B User B: accepts friend request from user A User A & User B: are now friends and appear on one another's friend list
I'm able to get user A to send the friend request and it appears on user B's screen. user B can accept the friend request and see user A in the friend list. However, user B cannot see user A on their friend list. This is because Parse.com doesn't allow you to update any user information other than for the PFUser.currentUser(). In doing some research, I've found that people have achieved this by using Cloud Code and the Master Key. I'm not as familiar with JavaScript, so this is a bit daunting. However, this is the JavaScript that will apparently do the trick.
Cloud Code:
Parse.Cloud.define('editUser', function(request, response) {
var userId = request.params.userId,
newColText = request.params.newColText;
var User = Parse.Object.extend('_User'),
user = new User({ objectId: userId });
user.set('new_col', newColText);
Parse.Cloud.useMasterKey();
user.save().then(function(user) {
response.success(user);
}, function(error) {
response.error(error)
});
});
Calling the cloud function from Objective-C:
```Objective-C
[PFCloud callFunction:@"editUser" withParameters:@{
@"userId": @"someuseridhere",
@"newColText": @"new text!"
}];
The swift equivalent is where I'm struggling I think. Here's what I have:
```Swift:
PFCloud.callFunctionInBackground("editUser", withParameters:nil) {
(result: AnyObject!, error: NSError!) -> Void in
if error == nil {
// result is "Hello world!"
}
}
My parameter is nil, but not sure of the syntax to add parameters or even what parameters I should be adding exactly to make this work. Hoping someone may have some thoughts?
Thanks a lot!
3 Answers
Stone Preston
42,016 PointsI got this working a few weeks ago. It's probably one of the most challenging things ive had to get working. working with cloud code was not as easy as I thought it was going to be.
this is the way I did it.
I have a friend request class in parse that has a fromUser that stores the user the request is from and a toUser attribute that stores who its to as well as a status attribute ("accepted, denied, etc)
I have a button that the user can press to accept a friend request.
when the button is pressed I call a cloud code function that adds the current user as a friend of the person who sent the request. I pass in the friendRequest object id as a parameter (you cant pass in an actual object, you just pass the id in and then query for it in cloud code)
then once that is done I add the person who sent the request as a friend of the current user.
this is the handler for the button press:
func handleAcceptButtonPressed(sender: UIButton) {
//the buttons tag stores the indexPath.row of the array
let friendRequest: PFObject = self.friendRequestsToCurrentUser[sender.tag] as PFObject
let fromUser: PFUser = friendRequest[FriendRequestKeyFrom] as PFUser
//call the cloud code function that adds the current user to the user who sent the request and pass in the friendRequest id as a parameter
PFCloud.callFunctionInBackground("addFriendToFriendsRelation", withParameters: ["friendRequest": friendRequest.objectId]) { (object:AnyObject!, error: NSError!) -> Void in
//add the person who sent the request as a friend of the current user
let friendsRelation: PFRelation = self.currentUser.relationForKey(UserKeyFriends)
friendsRelation.addObject(fromUser)
self.currentUser.saveInBackgroundWithBlock({ (succeeded: Bool, error: NSError!) -> Void in
if succeeded {
} else {
Utilities.handleError(error)
}
})
}
}
the cloud code function I wrote looks like this:
Parse.Cloud.define("addFriendToFriendsRelation", function(request, response) {
Parse.Cloud.useMasterKey();
//get the friend requestId from params
var friendRequestId = request.params.friendRequest;
var query = new Parse.Query("FriendRequest");
//get the friend request object
query.get(friendRequestId, {
success: function(friendRequest) {
//get the user the request was from
var fromUser = friendRequest.get("from");
//get the user the request is to
var toUser = friendRequest.get("to");
var relation = fromUser.relation("friends");
//add the user the request was to (the accepting user) to the fromUsers friends
relation.add(toUser);
//save the fromUser
fromUser.save(null, {
success: function() {
//saved the user, now edit the request status and save it
friendRequest.set("status", "accepted");
friendRequest.save(null, {
success: function() {
response.success("saved relation and updated friendRequest");
},
error: function(error) {
response.error(error);
}
});
},
error: function(error) {
response.error(error);
}
});
},
error: function(error) {
response.error(error);
}
});
});
this took me forever to get working by the way. I was not very familiar with javascript and all the nested functions were pretty confusing. But after a while and after a few questions on the parse google group I managed to make it work
Aaron Watkins
10,902 PointsOH. MY. GOD. :-o
That absolutely worked. I played with it for like 15 minutes and almost fell out of my chair. Thank you SOOO much Stone Preston . You're a genius!
Stone Preston
42,016 Pointsno problem : ) Glad it worked for you!
YOGESH TUCKLEY
2,077 PointsHow do you remove currentUser from friends PFRelation?
Aaron Watkins
10,902 PointsHi Priya!
I called this function from within my code. Here's the cloud code i was using:
Parse.Cloud.define("removeFriend", function(request, response)
{
//Example where an objectId is passed to a cloud function.
var id = request.params.friend;
//When getUser(id) is called a promise is returned. Notice the .then this means that once the promise is fulfilled it will continue. See getUser() function below.
getUser(id).then
(
//When the promise is fulfilled function(user) fires, and now we have our USER!
function(user)
{
//"user" is the person to who the current user wants to remove
response.success(user);
var currentUser = Parse.User.current().id;
var currentUserObject = Parse.User.current();
var relation = user.relation("friendsRelation");
relation.remove(currentUserObject);
user.save();
},
function(error)
{
response.error(error);
}
);
});
YOGESH TUCKLEY
2,077 PointsThanks for the script. I am going to give it a try. But where should I run it? I have "Parse.Cloud.define("addFriendToFriendsRelation", function(request, response)" in my main.js Should I just put this at the end of this function?
YOGESH TUCKLEY
2,077 PointsShould it look like this?
// Use Parse.Cloud.define to define as many cloud functions as you want. // For example: //Parse.Cloud.define("hello", function(request, response) { // response.success("Hello world!"); //});
Parse.Cloud.define("addFriendToFriendsRelation", function(request, response) {
Parse.Cloud.useMasterKey();
var friendRequestId = request.params.friendRequest;
var query = new Parse.Query("FriendRequest");
//get the friend request object
query.get(friendRequestId, {
success: function(friendRequest) {
//get the user the request was from
var fromUser = friendRequest.get("requestFrom");
//get the user the request is to
var toUser = friendRequest.get("requestTo");
var relation = fromUser.relation("friends");
//add the user the request was to (the accepting user) to the fromUsers friends
relation.add(toUser);
//save the fromUser
fromUser.save(null, {
success: function() {
//saved the user, now edit the request status and save it
friendRequest.set("requestStatus", "Accepted");
friendRequest.save(null, {
success: function() {
response.success("saved relation and updated friendRequest");
},
error: function(error) {
response.error(error);
}
});
},
error: function(error) {
response.error(error);
}
});
},
error: function(error) {
response.error(error);
}
});
});
Parse.Cloud.define("removeFriend", function(request, response) { //Example where an objectId is passed to a cloud function. var id = request.params.friend;
//When getUser(id) is called a promise is returned. Notice the
//.then this means that once the promise is fulfilled it will continue.
//See getUser() function below.
getUser(id).then
(
//When the promise is fulfilled function(user) fires, and now we have our USER!
function(user)
{
//"user" is the person to who the current user wants to remove
response.success(user);
var currentUser = Parse.User.current().id;
var currentUserObject = Parse.User.current();
var relation = user.relation("friendsRelation");
relation.remove(currentUserObject);
user.save();
},
function(error)
{
response.error(error);
}
);
});
Aaron Watkins
10,902 PointsYes - I believe that is how i have it set up. i have it put in my main.js. I call it from an @IBAction button (called removeFriend) and it works. Did that work for you?
YOGESH TUCKLEY
2,077 PointsI am trying to do that now. Thank you very much.
YOGESH TUCKLEY
2,077 Pointshi, this is the error I get "Error: ReferenceError: getUser is not defined at main.js:81:5 (Code: 141, Version: 1.5.0)" Below is my code:
void removeFriendship(PFUser *removeFriendUser)
{ [ProgressHUD show:@"Please wait..." Interaction:NO]; NSLog(@"removeFriendship %@", removeFriendUser); NSString *message = [NSString stringWithFormat:@"You are no longer friends with %@", removeFriendUser[PF_USER_FULLNAME]];
[PFCloud callFunctionInBackground:@"removeFriend" withParameters:@{@"friendRequest" : removeFriendUser.objectId} block:^(id object, NSError *error) {
if (!error) {
//remove the friend from currentUser PFRelation
PFRelation *friendsRelation = [[PFUser currentUser] relationForKey:@"friends"];
[friendsRelation removeObject:removeFriendUser];
//save the current user
[[PFUser currentUser] saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error)
{
if (!error) {
[ProgressHUD showSuccess:message];
}else [ProgressHUD showError:@"Unable to fulfill the request."];
}];
}
}];
}
Vincent Jardel
6,436 PointsHey Priya Tuckley , I've the same error like you : getUser is not defined at main.js. How do you solve this ? Please have a look on this url : http://stackoverflow.com/questions/30174768/delete-pfuser-with-cloud-code-parse-com-ios
Jeremy Conley
16,657 PointsI am currently trying to do this same thing, I'm not very familiar with working with cloud code. Before i was just trying to save the follower's objectID to an array key in the user class. Any help with how exactly pfrelations and adding users to them would be appreciated!
Aaron Watkins
10,902 PointsAaron Watkins
10,902 Pointssorry for the horrible code block format. not sure what i'm doing wrong there.