Relationship Mapping Restkit - ios

I have two tables say Articles and Authors. Each Article have many authors and same author can be come in multiple Articles. My Json response is looks like this.
{
"Articles": [
{
"artName": "ABC",
"artId": "1",
"Authors": [
{
"autName": "James",
"autId": "200",
"email": "james#xyz.com"
},
{
"autName": "Mark",
"autId": "201",
"email": "mark#xyz.com"
},
{
"autName": "Robert",
"autId": "202",
"email": "robert#xyz.com"
}
]
},
{
"artName": "BCD",
"artId": "2",
"Authors": [
{
"autName": "James",
"autId": "200",
"email": "james#xyz.com"
},
{
"autName": "Ben",
"autId": "204",
"email": "ben#xyz.com"
},
{
"autName": "Rayon",
"autId": "205",
"email": "rayon#xyz.com"
}
]
}
]
}
Mapping:
RKObjectManager *manager = [[RestKit sharedDataManager] objectManager];
RKEntityMapping *ArticleMapping = [RKEntityMapping mappingForEntityForName:#"Articles" inManagedObjectStore:manager.managedObjectStore];
ArticleMaping.identificationAttributes = #[#"artId"];
ArticleMaping addAttributeMappingsFromDictionary:#{
#"artId": #"artId",
}];
RKEntityMapping *AuthorMapping = [RKEntityMapping mappingForEntityForName:#"Authors" inManagedObjectStore:manager.managedObjectStore];
AuthorMapping.identificationAttributes = #[#"autId"];
AuthorMapping addAttributeMappingsFromDictionary:#{
#"autId": #"autId",
#"autName" : #"autName",
#"email" : #"email"
}];
[ArticleMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"Authors" toKeyPath:#"Authors" withMapping:AuthorMapping]];
I have made a relationship for Articles and Authors. It is mapping correctly, but when i try to fetch the authors for "artName" ABC. i am getting only 2 authors. but when i try to fetch data for "artName" BCD. i am getting 3 authors. when checked in DB, relationship key for record "James" is overwritten by record of BCD.
How can i access all the authors for both the articles.
Note: I am using Restkit 0.20
Thank you

The relationship between the 2 objects needs to be many to many or the new assignment will explicitly break the old assignment.
When you create your RKRelationshipMapping, ensure that you set the assignmentPolicy to RKUnionAssignmentPolicy. The default is RKSetAssignmentPolicy which could be removing the existing setting.

Related

Restkit NSInternalInconsistencyException Unable to add mapping for keyPath

Fyi, I'm not too familiar with Restkit's API. I prefer other means of deserializing json into domain objects; however, I've inherited a project and this is the quickest solution to fix a bug.
I'm trying to map "assignments" in the below json to "doctorAssignments" which is a 1-Many relationship in Core Data.
example json:
{
"id": 43,
"time_zone": "Mountain Time (US & Canada)",
"accepting_patients": true,
"auto_set_context_id": 44,
"audio_notifications": false,
"assignments": [
{
"id": 14,
"active_since": "2015-06-17T23:26:03Z",
"doctor": {
"id": 44,
"name": "Darth Vader PsyD",
"title": "Dr.",
"bio": "",
"type": "Doctor",
"profile_image_url": "https://cirrusmd-staging.s3.amazonaws.com/uploads/doctor/profile_image/43/darth.png?X-Amz-Expires=600&X-Amz-Date=20150618T163351Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAJGWZJVKLZCGMXJ2Q/20150618/us-east-1/s3/aws4_request&X-Amz-SignedHeaders=host&X-Amz-Signature=b0bc0163f4cf8c3c73572198c596565b0012a33331936baf4b14b9a255c0870f",
"credential_id": 214
}
}
],
"practice": {
"id": 2,
"name": "Test Practice",
"address": "",
"phone": "",
"fax": "",
"created_at": "2013-06-11T17:49:48Z",
"updated_at": "2013-06-11T17:49:48Z",
"email": "",
"city": "",
"state": "",
"zip": ""
}
}
Mapping:
+ (RKEntityMapping *)responseMapping {
if (_responseMapping == nil) {
_responseMapping = [RKEntityMapping mappingForEntityForName:[CMDUser entityName] inManagedObjectStore:[NSManagedObject managedObjectStore]];
_responseMapping.identificationAttributes = #[ CMDUserAttributes.userID, CMDUserAttributes.type ];
[_responseMapping addAttributeMappingsFromDictionary:#{
#"id" : CMDUserAttributes.userID,
#"type" : CMDUserAttributes.type,
#"profile_image_url" : CMDUserAttributes.profilePic,
#"credential_id" : CMDUserAttributes.credentialID,
#"name" : CMDUserAttributes.name,
#"last_name" : CMDUserAttributes.lastName,
#"first_name" : CMDUserAttributes.firstName,
#"allergies" : CMDUserAttributes.allergies,
#"medications" : CMDUserAttributes.medications,
#"history" : CMDUserAttributes.history,
#"email" : CMDUserAttributes.email,
#"location" : CMDUserAttributes.location,
#"zipcode" : CMDUserAttributes.zipcode,
#"gender" : CMDUserAttributes.gender,
#"dob" : CMDUserAttributes.dob,
#"relationship.state" : CMDUserAttributes.relationshipState,
#"relationship.status" : CMDUserAttributes.relationshipStatus,
#"relationship.onboarded_at" : CMDUserAttributes.onboardedAt,
#"auto_set_context_id" : CMDUserAttributes.autoSetContextID,
#"phone" : #"phone",
}];
}
// taking this line out removes the exception, but then the json isn't mapped
[_responseMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"assignments" toKeyPath:#"doctorAssignments" withMapping:[CMDDoctorAssignment mapping]]];
return _responseMapping;
}
On launch I get this error:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Unable to add mapping for keyPath doctorAssignments, one already exists...'
Note: I've omitted some fields in the json. In the mapping, I do NOT have
#"assignments": #"doctorAssignments".

RestKit sideload JSON association without CoreData

I am trying to get RestKit to use some sideloaded associations in my JSON, the JSON looks like the following:
{
"companies": [
{
"id": 1,
"name": "420...",
"street": "420 Kush St.",
"city": "Seattle",
"state": "WA",
"zip_code": "12345"
}
],
"user": {
"id": 1,
"email": "test#example.com",
"token": "1234567890",
"company_id": 1
}
}
I am not using the CoreData integration and need the company attribute of my user to fill in with the company found in the "companies" key of the above JSON. My current user mapping looks like:
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[GBUser class]];
[mapping addAttributeMappingsFromDictionary:#{
#"id": #"userId",
#"email": #"email"
}];
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
return [RKResponseDescriptor responseDescriptorWithMapping:mapping method:RKRequestMethodAny pathPattern:#"/api/v0/me" keyPath:#"user" statusCodes:statusCodes];
The simplest option is to write a couple of lines of code in the success block to associate the objects in the mapping result. You would use 2 response descriptors to map the users and companies separately and then combine them after the mapping has completed.

RestKit object mapping of list within list

the json api has a list of posts, and each post has a list of users that like this post.
post, user each has an entity in core data.
how RestKit do object mapping.
{
posts:[
{
"postid": 1,
"posttext": "post1",
"likeusers":[
{
"uid": 1,
"username": "user1"
},
{
"uid": 2,
"username": "user2"
}
]
},
{
"postid": 2,
"posttext": "post2",
"likeusers":[
{
"uid": 1,
"username": "user1"
},
{
"uid": 2,
"username": "user2"
}
]
}
]
}
Here is how to do the mapping:
// User mapping
RKEntityMapping *userMapping = [RKEntityMapping mappingForEntityForName:#"User"
inManagedObjectStore:yourManagedObjectStore];
userMapping.identificationAttributes = #[#"userID"];
[userMapping addAttributeMappingsFromDictionary:#{
#"uid": #"userID",
#"username": #"username",
}];
// Post mapping
RKEntityMapping *postMapping = [RKEntityMapping mappingForEntityForName:#"Post"
inManagedObjectStore:yourManagedObjectStore];
postMapping.identificationAttributes = #[#"postID"];
[postMapping addAttributeMappingsFromDictionary:#{
#"postid": #"postID",
#"posttext": #"postText",
}];
[postMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"likeusers"
toKeyPath:#"likeUsers" withMapping:userMapping]];
Hope it helps.

RestKit one-to-many relationship

I am having a problem with one-to-many relationships in my CoreData-backed entities.
My JSON looks like this:
[
{
"uuid": "0",
"title": "humor",
"providers": [{
"provider": {
"uuid": "1",
"title": "dilbert",
"sections": [{
"section": { "uuid":"1990", "title": "daily"},
"section": { "uuid":"1991", "title": "weekly"},
}],
},
"provider": {
"uuid": "2",
"title": "wizard of id",
},
"provider": {
"uuid": "3",
"title": "bc",
},
},],
},
{
"uuid": "22",
"title": "photo",
},
]
In my case, the top level object is a category, which can have 0..* providers, which can have 0..* sections.
Update: Just to wrap this up, the root of this problem is that the JSON is malformed. There should not be trailing commas in the dictionaries.
My RestKit mappings are:
RKEntityMapping *sectionMapping = [RKEntityMapping mappingForEntityForName:#"DHSection" inManagedObjectStore:managedObjectStore];
[sectionMapping addAttributeMappingsFromDictionary:#{
#"section.uuid" : #"uuid",
#"section.title" : #"title",
}];
sectionMapping.identificationAttributes = #[#"uuid"];
RKEntityMapping *providerMapping = [RKEntityMapping mappingForEntityForName:#"DHProvider" inManagedObjectStore:managedObjectStore];
[providerMapping addAttributeMappingsFromDictionary:#{
#"provider.uuid" : #"uuid",
#"provider.title" : #"title",
}];
providerMapping.identificationAttributes = #[#"uuid"];
RKRelationshipMapping *sectionRelationship = [RKRelationshipMapping relationshipMappingFromKeyPath:#"provider.sections" toKeyPath:#"sections" withMapping:sectionMapping];
[sectionRelationship setAssignmentPolicy:RKUnionAssignmentPolicy];
[providerMapping addPropertyMapping:sectionRelationship];
RKEntityMapping *categoryMapping = [RKEntityMapping mappingForEntityForName:#"DHCategory" inManagedObjectStore:managedObjectStore];
[categoryMapping addAttributeMappingsFromDictionary:#{
#"uuid" : #"uuid",
#"title" : #"title",
}];
categoryMapping.identificationAttributes = #[#"uuid"];
RKRelationshipMapping *providerRelationship = [RKRelationshipMapping relationshipMappingFromKeyPath:#"providers" toKeyPath:#"providers" withMapping:providerMapping];
[providerRelationship setAssignmentPolicy:RKUnionAssignmentPolicy];
[categoryMapping addPropertyMapping:providerRelationship];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:categoryMapping method:RKRequestMethodGET pathPattern:#"category/list.json" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:responseDescriptor];
[objectManager addFetchRequestBlock:^NSFetchRequest *(NSURL *URL) {
RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPattern:#"category/list.json"];
NSDictionary *argsDict = nil;
BOOL match = [pathMatcher matchesPath:[URL relativePath] tokenizeQueryStrings:NO parsedArguments:&argsDict];
if (match) {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"DHCategory"];
fetchRequest.sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:#"uuid" ascending:YES]];
return fetchRequest;
}
return nil;
}];
When RestKit parses the response, it correctly parses two categories, but it only loads the first provider and section.
Update 1 Nov 2013: The updated mapping above corrected the relationship mapping for sections to map from key path "provider.sections" vs "sections".
The problem may likely stem from the difference between the response and what is being mapped.
2013-11-01 10:40:06.670 xyz[58006:1003] D restkit.object_mapping:RKMapperOperation.m:377 Executing mapping operation for representation: (
{
providers = (
{
provider = {
sections = (
{
section = {
title = daily;
uuid = 1990;
};
}
);
title = dilbert;
uuid = 1;
};
}
);
title = humor;
uuid = 0;
},
...
while the response was
response.body=[
{
"uuid": "0",
"title": "humor",
"providers": [
{
"provider": {
"uuid": "1",
"title": "dilbert",
"sections": [{
"section": { "uuid":"1990", "title": "daily"},
"section": { "uuid":"1991", "title": "weekly"},
}
],
},
"provider": {
"uuid": "3",
"title": "wizard of id",
},
"provider": {
"uuid": "2",
"title": "bc",
},
},
],
},
...
Any ideas on how to fix or debug this?
Thanks,
Mike

RestKit: One to many relationship mapping

I'm trying to parse github's gist api response with RestKit. Here is a fragment of json:
{
"url": "https://api.github.com/gists/6004248",
...
"html_url": "https://gist.github.com/6004248",
"files": {
"ApplicationContext.h": {
"filename": "ApplicationContext.h",
"type": "text/plain",
"language": "Objective-C",
"raw_url": "https://gist.github.com/raw/6004248/4531c7534585b273c55ca71ce9020418b7ed271b/ApplicationContext.h",
"size": 481
},
"ApplicationContext.m": {
"filename": "ApplicationContext.m",
"type": "text/plain",
"language": "Objective-C",
"raw_url": "https://gist.github.com/raw/6004248/27a3881f9c5adde700b75199076a5ce259d0b568/ApplicationContext.m",
"size": 542
}
},
...
"user": {
...
},
"comments_url": "https://api.github.com/gists/6004248/comments"
},
Everything works fine, but i have problem with a files relationship. Here is a fragment of code responsible for files:
RKObjectMapping *gistMapping = [RKObjectMapping mappingForClass:[MBGist class]];
[gistMapping addAttributeMappingsFromDictionary: #{#"url": #"url", #"html_url": #"htmlUrl", #"description": #"description"}];
RKObjectMapping *fileMapping = [RKObjectMapping mappingForClass:[MBFile class]];
[fileMapping addAttributeMappingsFromDictionary:#{#"filename": #"filename", #"language": #"language", #"type":#"type"}];
[gistMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"files" toKeyPath:#"files" withMapping:fileMapping]];
but I have empty files arrays in my MBGist class objects.
Can anybody help me with it?
Best Regards,
MichaƂ
Please refer to Handling Dynamic Nesting Attributes section in Restkit ObjectMapping

Resources