9

Scenario = I am slowly but surely wrapping my head around what is going on with Parse's cloud code features. I just need some help from those who would like to answer some short, relatively simple questions about what is going on in some sample cloud code functions.

The code I will use in this example is below

1) 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)
    });

});

2) called from iOS

[PFCloud callFunction:@"editUser" withParameters:@{

    @"userId": @"someuseridhere",
    @"newColText": @"new text!"

}];

This code was taken from here

Question 1 =

(request, response) 

I am confused by what this is. Is this like typecasting in iOS where I am saying (in the iOS call) I want to pass an NSString into this function ("userId") and inside the cloud code function I'm going to call it "request"? Is that what's going on here?

Question 2 =

Parse.Object.extend('_User') 

Is this grabbing the "User" class from the Parse database so that a "PFObject" of sorts can update it by creating a new "user" in the line below it?

Is this like a...

PFObject *userObject = [PFObject objectWithClassName:@"User"]?

Question 3 =

user.set('new_col', newColText)

This obviously 'sets' the values to be saved to the PFUser (~I think). I know that the "newColText" variable is the text that is to be set - but what is 'new_col'? Only thing I can think of is that this sets the name of a new column in the database of whatever type is being passed through the "request"?

Is this like a...

[[PFUser currentUser] setObject: forKey:]

Question 4 =

Parse.Cloud.useMasterKey() 

Without getting too technical, is this basically all I have to type before I can edit a "User" object from another User?

Question 5 =

user.save().then(function(user) {
        response.success(user);
    }

Is this like a...

[user saveInBackgroundWithBlock:]? 

and if so, is

function(error) {
        response.error(error)

just setting what happens if there is an error in the saveInBackgroundWithBlock?

Please keep in mind, I know iOS - not JavaScript. So try to be as descriptive as possible to someone who understands the Apple realm.

Community
  • 1
  • 1
Tom Testicool
  • 563
  • 7
  • 26
  • This is an excellent question. Try looking up some backbone.js tutorials, thats how a lot of this cloud code works. – Nick H Jul 05 '15 at 18:59

2 Answers2

11

Here's my take on your questions:

  1. The request parameter is for you to access everything that is part of the request/call to your cloud function, it includes the parameters passed (request.params), the User that is authenticated on the client (request.user) and some other things you can learn about in the documentation. The response is for you to send information back to the calling code, you generally call response.success() or response.error() with an optional string/object/etc that gets included in the response, again documentation here.
  2. That's a way of creating an instance of a User, which because it is a special internal class is named _User instead, same with _Role and _Installation. It is creating an instance of the user with an ID, not creating a new one (which wouldn't have an ID until saved). When you create an object this way you can "patch" it by just changing the properties you want updated.
  3. Again, look at the documentation or an example, the first parameter is the column name (it will be created if it doesn't exist), the second value is what you want that column set to.
  4. You have to do Parse.Cloud.useMasterKey() when you need to do something that the user logged into the client doesn't have permission to do. It means "ignore all security, I know what I'm doing".
  5. You're seeing a promise chain, each step in the chain allows you to pass in a "success" handler and an optional "error" handler. There is some great documentation. It is super handy when you want to do a couple of things in order, e.g.

Sample code:

var post = new Parse.Object('Post');
var comment = new Parse.Object('Comment');
// assume we set a bunch of properties on the post and comment here
post.save().then(function() {
    // we know the post is saved, so now we can reference it from our comment
    comment.set('post', post);
    // return the comment save promise, so we can keep chaining
    return comment.save();
}).then(function() {
    // success!
    response.success();
}, function(error) {
    // uh oh!
    // this catches errors anywhere in the chain
    response.error(error);
});
EmilyP
  • 118
  • 1
  • 12
Timothy Walters
  • 16,866
  • 2
  • 41
  • 49
  • This is a great answer. I'll add to #2 which is while you can extend the _User object using Parse.Object.extend() it's preferred to use the Parse.User() class itself. – Troy Sandal Jul 29 '14 at 02:14
  • Thank you for your answer @Timothy Walters! I know it's been a while coming but I've been busy. I have a couple of quick follow up questions about line `user = new User({ objectId: userId });` **1)** the "new" part. Is that making a "brand new" user, or grabbing the existing user of objectId: userID and updating it? **2)** If the latter is true, than instead of "grabbing" a user at the "objectId" column, can I grab them at the "userID" column? Like... `user = new User({ userID: userId });` – Tom Testicool Aug 06 '14 at 15:35
  • Regarding 4) Parse.Cloud.useMasterKey(); has been deprecated in Parse Server version 2.3.0 (Dec 7, 2016). From that version on, it is a no-op (it does nothing). You should now insert the {useMasterKey:true} optional parameter to each of the methods that need to override the ACL or CLP in your code. – alvaro Jun 01 '17 at 00:45
3

I'm pretty much at the same place as you are, but here are my thoughts:

  1. No, these are the parameters received by the function. When something calls the editUser cloud function, you'll have those two objects to use: request & response. The request is basically what the iOS device sent to the server, and response is what the server will send to the iOS device.
  2. Not quite that. It's like creating a subclass of _User.
  3. Think of Parse objects types as a database table and it's instances as rows. The set will set (derp) the value of 'newColText' to the attribute/column 'new_col'.
  4. Not sure, never used that function as I don't handle User objects. But might be that.
  5. Pretty much that. But it's more sort of like (pseudo-code, mixing JS with Obj-C):

[user saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error){ if(error){ response.error(error); // mark the function as failed and return the error object to the iOS device } else{ response.success(user); // mark the function call as successful and return the user object to the iOS device } }];

B.R.W.
  • 1,566
  • 9
  • 15
  • your answers helped me more than the entire Parse docs on Cloud Code. But still questions 2 and 4 are a bit iffy for me. So because of that I will leave this question unanswered for now but I am up voting answer in the mean time. If I figure this out until then Ill mark your answer as correct. – Tom Testicool Jul 28 '14 at 21:05
  • Fair enough :) But about the question 2: you probably need the `extend("_User")` because you have added at least one attribute to the default `_User` class. If you instantiate a `_User` object, it would not have those new attributes ('new_col', for example), and then you wouldn't be able to `set('new_col', new_col_value)` on that object. Again, I'm not a pro on Cloud Code, but that's what I understood from the docs. Have fun! – B.R.W. Jul 28 '14 at 21:59
  • I'm far from a cloud code pro myself. But hey tell me this though because this would clear up a lot. Under question 2 *Parse.Object.extend('_User')* - you are saying from what class I want to edit - then you *user = new User({ objectId: userId });* which creates the "PFObject" like thing so you can set the new data and then save the object. **Never** having created a new object, just updated an existing. Is that correct? – Tom Testicool Jul 28 '14 at 23:15