Parse.com Store data from one object into another object - objective-c

I'm creating an app using parse as the backend, I have three Classes (User,Student,School). I currently have a pointer between the User class and the Student Class so if I enter a new student I can create a relation to the User.
My issue is I am trying to do the same for the School class, this class is a pre-populated class and when I am creating a new student I need to reference that class by school_id that is in the student class as a pointer.
images of my class are
So from the images you can see that the object_id from the user class is the parent_id in the students class. Now I need to have the object_id or school_id from the School class as the school_id in the Student Class.
Expected results:
User"jamiemw" -> Student"johnnie Williams" -> School"Southwind"
below is what I've tried with
PFObject *kid = [PFObject objectWithClassName:#"Kids"];
kid[#"child_name"] = #"Johnnie Williams";
kid[#"age"] = #"14";
kid[#"date_of_birth"] = #"02/27/2001";
[kid setObject:[PFUser currentUser] forKey:#"parent_id"];
//this is what does not work.
[kid setValue:[PFQuery queryWithClassName:#"Schools"] forKey:#"student_id"];
[kid save];
PFQuery *query = [PFQuery queryWithClassName:#"Kids"];
[query whereKey:#"parent_id" equalTo:[PFUser currentUser]];
[query findObjectsInBackgroundWithBlock:^(NSArray *results, NSError *error)
{
for(int i = 0; i <= results.count; i++){
NSLog(#"%#", [results objectAtIndex:i]);
}
}];

Your first problem is that [PFQuery queryWithClassName] returns a PFQuery, as shown in the documentation. Storing this instance of a query is probably not going to give you any useful information, so you will want to first perform the query you instantiated and extract the desired data from that before saving it to a key in the kid PFObject.
The second problem I noticed is that there doesn't appear to be a key student_id for any of the tables you posted screenshots of above. I'm assuming this was a typo and you meant to write [kid setValue:[PFQuery queryWithClassName:#"Schools"] forKey:#"school_id"];
Replacing the above mentioned line of code with the following should achieve the desired result:
[PFQuery queryWithClassName:#"Schools"];
[query whereKey:#"school_id" equalTo:#"southwindE123"];
// getFirstObject can be used here because school_id
// is assumed to be a unique key
PFObject *school = [query getFirstObject];
[kid setValue:school forKey:#"school_id"];

Related

Why can not access to pointer object of _User in Parse?

I have a table called "Event" with public read and write access.
Inside this table I have one field called "user". This field is a pointer to _User table with public read and only user write access.
This is my code:
PFQuery *query = [PFQuery queryWithClassName:#"Event"];
[query whereKey:#"objectId" equalTo:self.objID];
[query getObjectInBackgroundWithId:self.objID block:^(PFObject *object, NSError *error) {
if (!error)
{
PFUser *host = [object objectForKey:#"user"];
NSLog(#"HOST == %#",host);
self.hostId = host.objectId;
}
]);
Now problem is, if userA create a row in Event table called eventA and userB create an Event called eventB. if UserA query eventB cannot access to userB information. However, if userA query eventA, it can access to itself information.
Answer is pretty much easy. It seems that I need to include key in my query:
[query includeKey:#"user"];

Parse.com combine nested query

I am new to using parse, and currently adding parse to an app that uses SOAP web services to replace them.
Now I come a little stuck, as due to having it done in MySQL and php I am trying to translate the logic from the tables and code to parse.
I have a function that I have written and it achieves exactly what I am after, however I just think its wrong and can be done better, for starters I am not calling findObjectsInBackground, which I know I need to.
I am trying to take this result and then reload a tableView.
NSMutableArray *activityfeed = [NSMutableArray new];
//get current user
PFUser *user = [PFUser currentUser];
if (user != nil) {
PFQuery *query = [PFQuery queryWithClassName:#"Event"];
//get event that user is involved in
[query whereKey:#"invited" equalTo:user];
//get the events
NSArray *events = [query findObjects];
//loop over the events
for (PFObject *event in events) {
//owner is a pointer to the users class
PFUser *owner = event[#"owner"];
if (![user.objectId isEqualToString:owner.objectId]) {
//ignore the info for the logged in user for now
//invited is a relation so one event has many users
PFRelation *relation = [event relationForKey:#"invited"];
PFQuery *query = [relation query];
[query orderByDescending:#"dateinvited"];
[query addDescendingOrder:#"dateaccepted"];
//get the friends that are involved with the event
NSArray *friends = [query findObjects];
for (PFUser *friend in friends) {//Perform logic checks here and then add to activityfeed}
}
}
}
return activityfeed;
So my logic above gets the current user, then get all the events that user is involved with, then get all the other people involved with that event and then work out what to display.
Is there a more efficient way of doing the above?
Usually we use whereKey:matchesQuery in cases like this. Take some research on this.
This question may help you find out some solution.

Correct way to user PFQuery to query relational data like Pointer

Ok so let's say I have a post of an event, and users can click a button to notify that they are attending this event. As of now I have a class called Activity in which I save the current user and the event to this class, so theres 2 columns. If I want to query all users who are attending an event, am I headed in the right direction to do this, or am I doing it complentely wrong?
So far I have:
-(PFQuery*)queryForTable {
PFQuery *activityQuery = [PFQuery queryWithClassName:#"Activity"];
[activityQuery whereKey:#"event" equalTo:self.event];
[activityQuery includeKey:#"going"];
return activityQuery;
}
cellForRowAtIndex:
UILabel *title = (UILabel*) [cell viewWithTag:1];
title.text = [object objectForKey:#"going.username"];
You can actually see what you have been done in the Parse dashboard. That's also their purpose to develop a data browser like this. It's way more convenient.
For your case, you just need to check whether the type is Pointer. Try to click on that if so in the dashboard. It will direct you to the target object.
Would suggest you to read this article first, it's about the relation:
https://parse.com/docs/relations_guide
Then, you should go check the iOS SDK tutorial:
includeKey is definitely what you need to use.
Here is the sample from Parse:
PFQuery *query = [PFQuery queryWithClassName:#"Comment"];
// Retrieve the most recent ones
[query orderByDescending:#"createdAt"];
// Only retrieve the last ten
query.limit = 10;
// Include the post data with each comment
[query includeKey:#"post"];
[query findObjectsInBackgroundWithBlock:^(NSArray *comments, NSError *error) {
// Comments now contains the last ten comments, and the "post" field
// has been populated. For example:
for (PFObject *comment in comments) {
// This does not require a network access.
PFObject *post = comment[#"post"];
NSLog(#"retrieved related post: %#", post);
}
}];
Your code looks right on so far. Then to retrieve your Activity class values, you can use:
PFQuery *activityQuery = [PFQuery queryWithClassName:#"Activity"];
// Set contraints here, example:
[activityQuery setLimit:100];
[query findObjectsInBackgroundWithBlock:^(NSArray *array, NSError *error) {
if (!error) {
// Success, do something with your objects.
}
}];

Parse.com - Getting pointer data contained in [PFUser currentUser]

I am using the Parse.com iOS SDK, and I don't know what method I need to call to make sure that the PFUser currentUser contains the data for each pointer contained in it. It is probably very simple, but, as a beginner with this platform, I cannot find a solution.
Just to clarify, I am trying to get the username item in the following. It looks like it is always null, even though I am calling [[PFUser currentUser] fetchIfNeeded] before proceeding:
[[[PFUser currentUser] objectForKey:#"partner"] objectForKey:#"username"];
Thank you,
Andrea
You can do it in a single query by using includeKey:
PFQuery *query = [PFUser query];
[query includeKey:#"partner"];
[query includeKey:#"anotherPointerColumnName"];
[query getObjectInBackgroundWithId:[[PFUser currentUser] objectId]
block:^(PFObject *populatedUser, NSError *error) {
PFObject *partner = populatedUser[#"partner"];
PFObject *another = populatedUser[#"anotherPointerColumnName"];
}];
You can also use deeper levels, so if partner contained a pointer in it you needed called deeperPointerColumnName:
[query includeKey:#"partner.deeperPointerColumnName"];
Then in your completion block you can read it after you get the partner:
PFObject *partner = populatedUser[#"partner"];
PFObject *deeper = partner[#"deeperPointerColumnName"];
Well, I found a workaround by myself. It looks like the solution is to call the fetch method on the pointer before proceeding:
[[[PFUser currentUser] objectForKey:#"partner"] fetch];
If there is a cleaner and swifter way of doing it (automatically for instance) I would really appreciate any advice.

parse.com API - how to run a query inside parse classes files?

I will try to explain myself as best as I can.
My app has a login & sign Up using the Parse API .
after signing or logging the User see a page with a Button and a Text Field which he can write Numbers in it ,
let's say he write , for example: 1234.
the button job is to save the data from the text field
Now i'm sure my Button method isn't the best way, but it's work :-)
NSString *whoIsTheUser = [PFUser currentUser];
NSString *phoneNumbers = phoneNumberField.text ;
NSString *fullData = [NSString stringWithFormat:#" %# , %#", whoIsTheUser, phoneNumbers];
NSLog(#" %#, %# ", whoIsTheUser, phoneNumbers);
PFObject *addValues= [PFObject objectWithClassName:#"phoneNumber"];
[addValues setObject: fullData forKey:#"numbers"];
[addValues saveInBackground];
So now what i'm having is the data saved to parse site under class of Numbers (forKey:#"numbers")
and it's look like this :
<PFUser:hqExhaYaIN:(null)> {email = "buffo#yahoo.com";username = buffo;} , 1234
what I'm trying to do is to add another button which going to check if theres another user
who wrote the same numbers and then send an alert or do something .
I have tried to read about the PFQuery but didn't find any solution.
is it even possible to run Query in the classes name ? or maybe theres another way to do it ( within the parse site ) ?
thank you so much for any suggestion !
It looks like you need to split up fullData in your parse objects and do something like this
PFQuery* numQuery = [PFQuery queryWithClassName:#"phoneNumber"];
[numQuery whereKey:#"numbers" equalTo:phoneNumbers];
[numQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
{
if(!error)
{
for(PFObject *numObject in objects)
{
//Do what you need to do here
}
}
else
{
//handle error
}
}
EDIT - this means you would save your PFObjects like this
PFObject *addValues= [PFObject objectWithClassName:#"phoneNumber"];
[addValues setObject: phoneNumbers forKey:#"numbers"];
[addValues setObject: whoIsTheUser forKey:#"theUser"];
[addValues saveInBackground];
i hope it's going to help someone like it's helps me , if you want to query for info without the user info use those lines
PFQuery* numQuery = [PFQuery queryWithClassName:#"phoneNumber"];
[numQuery whereKey:#"numbers" equalTo:phoneNumbers];
[numQuery whereKey:#"theUser" notEqualTo:[PFUser currentUser]];
[numQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
all I had to do is add notEqualTo and CurrentUser :-)