Assertion failure in +[Sync changes:inEntityNamed:predicate:parent:inContext:dataStack:completion:] - ios

I'm using Sync from HyperOslo i get a simple JSON object:
Printed json object (user) =>
[{
email = "email#email.fr";
name = "Damian Menestrel";
}]
...to convert in Core Data User with the method:
Sync.changes(user , inEntityNamed: "User", dataStack: DataManager.dataStack, completion: { (response ) -> Void in
})
The app crash with this error:
Assertion failure in +[Sync
changes:inEntityNamed:predicate:parent:inContext:dataStack:completion:],
.../Pods/Sync/Source/Sync.m:77
Where this error come from?
My CodeData model is :
User.swift
import Foundation
import CoreData
import UIKit
class User: NSManagedObject {
#NSManaged var email: String?
#NSManaged var name: String?
}

Short answer:
Just add a remoteID attribute to your Core Data model as a primary key and it will work. This will map to the id attribute in your JSON.
Long answer:
Taken from the Primary Key section on Sync's README.
Sync requires your entities to have a primary key, this is important
for diffing otherwise Sync doesn’t know how to differentiate between
entries.
By default Sync uses id from the JSON and remoteID from Core
Data as the primary key. You can mark any attribute as primary key by
adding hyper.isPrimaryKey and the value YES.
For example in our Designer
News
project we have a Comment entity that uses body as the primary
key.

Related

How to change JSON key name Swift?

In my application I have used the same keyname to get data everywhere, now in json response that data is same but in one place the keyname is changed so I want to rename the keyname of the array in my json this is what I am getting searched on stack overflow but unable to find any reliable way please guide me any good way to do it
{"status":"success","msg":"deleted","pro_data":[]}
I want JSON with these keys:
{"status":"success","msg":"deleted","Images":[]}
you can use Codable to create JSON model and in that you can customise you key.
I assume your JSON response ({"status":"success","msg":"deleted","pro_data":[]}) available in Data format.
So, See the following code which are used to create JSON model for your data.
struct WSModel: Codable {
var status : String?
var msg : Int?
var Images : [Any]?
enum CodingKeys: String, CodingKey {
case currentPage = "status"
case msg = "msg"
case Images = "pro_data"
}
}
Due to there aren't any data type inside your array I have keep Any type of data.This code is work for when keys in response are "status", "msg", "pro_data".
Try this code and let me know still an issue. I hope this will work for you.
I assume your issue is that you want to continue to use "Images":[] key, without having to change rest of your code.
In your JSON response that you want to change, you can try something like this.
response["Images"] = response["pro_data"]

How to read results using Apollo Client for iOS

I'm trying to use GraphQL in iOS with Apollo Client. I have the following mutation:
login(user: String!, password: String!): UserType
and the UserType looks like this:
id: ID
user: String!
password: String!
name: String
lastname: String
email: Email!
groups: [GroupType]
In iOS, I have configured aopllo client as the doc says and is working perfectly, but I don't know how to get access to every field in the response. When the login success I want to read the json I receive as response with the UserType fields, so, I'm doing this:
apolloClient.perform(mutation: loginMutation) {
resultsGQL, error in
...
}
My question is, how can I read every field from resultGQL which belongs to the UserType data defined in my grapql schema?
Regards
The question is not 100% clear, since it is missing some code your mutation: A GraphQL mutation has to return at least one value, which you have to define. Since i'm not sure about your method
login(user: String!, password: String!): UserType
i am giving you a simple example for updating an existing userProfile with a GraphQL mutation and then returning every field being defined in your schema for userType.
Let us assume you have a userType (and therefore know the corresponding userId) and you want to modify the email:
mutation updateUserProfile($id: ID!, $newEmail: String) {
updateUser(id: $id, email: $newEmail) {
id
user
password
name
lastName
email
}
}
As you can see, after executing
updateUser(id: $id, email: $newEmail)
all return values are defined inside the following {...} parentheses and are therefore accessible in your callback variable
resultsGQL
That means:
apolloClient.perform(mutation: loginMutation) { resultsGQL, error in
if let results = resultsGQL?.data {
// "results" can now access all data from userType
}
}
Since you defined all entities of your userType schema to be returned from the mutation, you can access them now in your callback variable.

In my neo4j db, the graphql mutation is not working as expected for 2 types

I am using neo4j dB and apollo-graphql server for my test project. I am trying to create a Q&A app where a user could create a question (with unique id) and then it would be answered by other user (similar to stackoverflow but with very minimum features).I want to create relationship between "Questions" node and "Users" node in my neo4j db via mutation.
so, in the mutations I created User Type and Question Type. But when I am trying to create relation between the user (who created question) and the question, the mutation is not working as expected.
Here is the graphql schema...
type Question {
questionID: Int! # unique id for a particular question
title: String! # Question Title
details: String!
createdBy: User!
}
type User {
userID: Int!
name: String!
email: String
questions: [Question] # specific questions related to the user
}
type Mutation {
createUser(name: String!, userID: Int!): [User]
createQuestion(questionID: Int!, title: String!, details: String!,userID: Int! ): Question
And here is the mutation snippet from resolver...
Mutation: {
createQuestion(_,params){
let session = driver.session();
let query = "MERGE (q:Questions {questionID:{questionID},title:
{title},details:{details},userID:{userID}})-[:CREATED_BY]->
(u:Users{userID:{userID}}) RETURN q;"
return session.run(query,params)
.then( result => {
return result.records.map( record => {
return record.get("q").properties
}
)
}
)
},
}
I had already inserted a dummy user with unique userID "1" in neo4j db before running this mutation query. And I ran this "createQuestion" mutation in graphiQL to create a question for the existing user and so I passed userID "1" as argument,
//createQuestion(questionID: Int!, title: String!, details: String!,userID: Int! )
And after running this mutation query, I was hoping to get a relation of [:CREATED_BY] between the existing user and the question created,
But my database now has 2 users with same user id "1" (i.e. one more user with same userid "1" has been inserted and the relationship is now present between this newly inserted user and question node).
What I need is to avoid to create new duplicate user with same id , and rather just to create relationship between the existing user and the question. So could someone please let me know what I have mistaken here ?
You must change your query:
let query = "
MERGE (u:Users{userID:{userID}})
MERGE (q:Questions {questionID:{questionID},title:
{title},details:{details},userID:{userID}})
MERGE (q)-[:CREATED_BY]->(u)
RETURN q;"
As you have the questionID already in place, which i'm guessing is a unique identifier I would change the query to:
let query = "
MERGE (u:Users{userID:{userID}})
MERGE (q:Questions {questionID:{questionID})
ON CREATE SET q.title=
{title},q.details={details}
MERGE (q)-[:CREATED_BY]->(u)
RETURN q;"
Notice I also removed userID property from question as you do not need it as you already create a relationship from User to Question
Edit:
You can solve the problem from the comment in two ways:
by adding UserID property to question:
let query = "
MERGE (u:Users{userID:{userID}})
MERGE (q:Questions {questionID:{questionID},userID:{userID}})
ON CREATE SET q.title= {title},q.details={details},
MERGE (q)-[:CREATED_BY]->(u)
RETURN q;"
Or with local merges:
let query = "
MERGE (u:Users{userID:{userID}})
MERGE (u)<-[:CREATED_BY]-(q:Questions {questionID:{questionID}})
ON CREATE SET q.title= {title},q.details={details},
RETURN q;"

Vue set Firebase data using Key

I'm having trouble with a Vue Method that both pushes a new deal to one Firebase ref and sets data in another. The issues lies when the method sets data. My current method is unable to get the key of deal that it is writing to the dealsRef in order to save it in the dealsRel.
Firebase Refs:
// Firebase reference to deals
const dealsRef = db.ref('deals');
// Firebase reference to deal "relations"
const dealsRel = db.ref('dealsRel');
Method:
addDeal() {
// Push new Deal to Firebase
dealsRef.push(this.newDeal),
//Issue is here:
dealsRel.child(this.newDeal.provider).child( How to get key of object pushed in line above? ).set(true)
},
JSON Structure:
 
deals
-KjtfMcfuZkP_kKP708x
provider: "-KQ1if2Zv3R9FdkJz_1_"
title: "Deal Name"
dealsrel
-KQ1if2Zv3R9FdkJz_1_" // Provider Firebase ID
Needs to be "-KjtfMcfuZkP_kKP708x": true //Firebase ID of deal
...
Was able to solve using Firebase .getKey() like so:
var theKey = dealsRef.push(this.newDeal).getKey()
dealsRel.child(this.newDeal.provider).child(theKey).set(true)

When to use uid and when to use $id in angularfire

$id The key where this record is stored. The same as obj.$ref().key
To get the id of an item in a $firebaseArray within ng-repeat, call $id on that item.
These two are from the angular fire reference:
https://github.com/firebase/angularfire/blob/master/docs/reference.md
What I understand is if there is firebase object created with :
var object = $firebaseObject(objectRef);
then I can use uid always.
uid : object.uid
But I saw examples where the firebase auth user is used with $id.
return Auth.$requireSignIn().then(function (firebaseUser) {
return Users.getProfile(firebaseUser.uid).$loaded().then(function (profile) {
**profile.uid or profile.$id here**
Also is it possible the object to have uid but not to have $id (obj.$ref().key). Aren't they the same thing? Does the object have to be loaded first with $loaded() to use $id or uid?
Regards
You seem to be confusing two concepts:
the object.$id of an AngularFire object contains the key of that object in the Firebase Database.
a firebaseUser.uid in Firebase terms is the identification of a Firebase Authentication user.
It is common to store your Firebase Authentication users in the database under their uid, in which case user.$id would be their uid. But they are still inherently different things.
Users
uid1
displayName: "makkasi"
uid2
displayName: "Frank van Puffelen"
So if you we look at the code snippet you shared:
return Auth.$requireSignIn().then(function (firebaseUser) {
return Users.getProfile(firebaseUser.uid).$loaded().then(function (profile) {
The first line requires that the user is signed-in; only then will it execute the next line with the firebaseUser that was signed in. This is a regular JavaScript object (firebase.User), not an AngularFire $firebaseObject.
The second line then uses the firebaseUser.uid property (the identification of that user) to load the user's profile from the database into an AngularFire $firebaseObject. Once that profile is loaded, it executes the third line.
If the users are stored in the database under their uid, at this stage profile.$id and firebaseUser.uid will be the same value.

Resources