Multiple RKRelationshipMapping with same toKeyPath - ios

I have a problem using multiple RKRelationshipMappings with same toKeyPath (destinationKeyPath).
I have had success with using one RKRelationshipMapping to one toKeyPath but I'm unable to attach a second RKRelationshipMappings with the same toKeyPath.
Code with one RKRelationshipMapping that works:
RKObjectMapping *someObjectRequestMapping = [RKObjectMapping requestMapping];
[someObjectRequestMapping addAttributeMappingsFromDictionary:#{#"prop1" : #"prop_1", #"prop2" : #"prop_2"}];
RKObjectMapping *firstSubObjectMapping = [RKObjectMapping requestMapping];
[firstSubObjectMapping addAttributeMappingsFromDictionary:#{#"subProp1" : #"sub_prop1", #"subProp2" : #"sub_prop2"}];
[someObjectRequestMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"prop3"
toKeyPath:#"prop_3"
withMapping:firstSubObjectMapping];
However, if i want to add another RKRelationshipMapping to "someObjectRequestMapping" with the same toKeyPath ("prop_3") the RestKit fails with error:
*'NSInternalInconsistencyException', reason: 'Unable to add mapping for keyPath invites_attributes, one already exists...'*
Code with two RKRelationshipMappings that fails:
RKObjectMapping *someObjectRequestMapping = [RKObjectMapping requestMapping];
[someObjectRequestMapping addAttributeMappingsFromDictionary:#{#"prop1" : #"prop_1", #"prop2" : #"prop_2"}];
RKObjectMapping *firstSubObjectMapping = [RKObjectMapping requestMapping];
[firstSubObjectMapping addAttributeMappingsFromDictionary:#{#"subProp1" : #"sub_prop1", #"subProp2" : #"sub_prop2"}];
RKObjectMapping *secondSubObjectMapping = [RKObjectMapping requestMapping];
[secondSubObjectMapping addAttributeMappingsFromDictionary:#{#"subProp2" : #"sub_prop2", #"subProp3" : #"sub_prop3"}];
[someObjectRequestMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"prop3"
toKeyPath:#"prop_3"
withMapping:firstSubObjectMapping];
[someObjectRequestMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"prop4"
toKeyPath:#"prop_3"
withMapping:secondSubObjectMapping];
The mapping is used in RKRequestDescriptor.
Any help would be greatly appreciated.
Best Regards,
Damir

The error is quite clear, RestKit will not allow ambiguity so you can only have one mapping per key path.
Usually if this was for a response descriptor you would use a dynamic mapping to determine which relationship mapping was appropriate. For a request descriptor you can do something similar yourself where you analyse the object to be sent and decide which mapping is appropriate. This does mean having 2 different mappings and choosing between them manually. This could also be done using multiple RKObjectManagers, each configured with a different set of mappings.

Related

How to Rectify the Relationship Fault in CoreData While parsing RESTKIT?

I want to Store the EY_ConnectionUsage Entity value to the EY_Connection entity Cell.I have Added two Entities with Attributes and Created Relationship with name usageData.But this Shows error "<'usageData' Relationship Fault>".This is a Method I wrote to map the RESTKIT value to CoreData.
DataAccessHandler.m
+(void)createConnectionMappingWithStore:(RKManagedObjectStore *)managedObjectStore saveInDelegate:(AppDelegate *)appDelegate{
NSLog(#"appdele==>>%#",appDelegate);
RKEntityMapping *connectionMapping = [RKEntityMapping mappingForEntityForName:#"EY_Connections" inManagedObjectStore:managedObjectStore];
connectionMapping.identificationAttributes = #[#"connectionNumber"];
[connectionMapping addAttributeMappingsFromDictionary:#{ #"ServiceNo" : #"connectionServiceNumber", #"Name" : #"connectionName", #"Region" : #"connectionRegion", #"Phase" : #"connectionPhase",
#"Circle" : #"connectionCircle", #"Section" : #"connectionSection", #"Load" : #"connectionLoad",
#"Distribution" : #"connectionDistribution", #"MeterNo" : #"connectionMeterNumber", #"ConnectionNumber" : #"connectionNumber", #"Address" : #"connectionAddress", #"ServiceStatus" : #"connectionStatus"}];
RKEntityMapping *connectionUsageMapping = [RKEntityMapping mappingForEntityForName:#"EY_ConnectionUsage" inManagedObjectStore:managedObjectStore];
connectionUsageMapping.identificationAttributes = #[#"usageAssessmentDate"];
[connectionUsageMapping addAttributeMappingsFromDictionary:#{ #"assessment_date" : #"usageAssessmentDate", #"reading" : #"usageReading", #"units" : #"usageUnits", #"amount" : #"usageAmount",
#"payment_date" : #"usagePaymentDate", #"status" : #"usageStatus"}];
[connectionMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"usage" toKeyPath:#"usageData" withMapping:connectionUsageMapping]];
RKResponseDescriptor *articleListResponseDescriptor =
[RKResponseDescriptor responseDescriptorWithMapping:connectionMapping
method:RKRequestMethodGET
pathPattern:#"user_history/consumer/data.json"
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)
];
[appDelegate createObjectManagerForurl:#"http://sciflare.com/energyly/api/" andAddResponseDescriptor:articleListResponseDescriptor];
[AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
}
<'usageData' Relationship Fault>
This means that the relationship data hasn't been loaded yet, because you haven't tried to use it. Logging the object isn't enough to load the data. The whole point of the faulting system is to prevent too much data being loaded into memory at the same time.
So, basically, it isn't a problem that it's a fault. When you try to use it the data will be populated and everything will be fine.
CoreData says that 'load only needed data'. If we are trying to fetch unwanted data then coredata shows 'FAULT'.
Foe more detail please go through CoreData Fault

Using Keys as Values in RestKit

So, we have an API that spits out:
{
"2013-12-13": [subobject1, subobject2, subobjects3],
"2013-12-14": [subobject4, subobject5],
...
}
I'm not sure, though, how to parse things in RestKit where the key changes dynamically.
I'd probably like to parse it into a list of objects that have a date, and the list of subobjects.
Any thoughts?
You need to create a mapping something like:
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[XXX class]];
[mapping addAttributeMappingFromKeyOfRepresentationToAttribute:#"date"];
[mapping addAttributeMappingsFromDictionary:#{
#"(date)": #"values"
}];
Where your XXX class has properties for date (NSDate) and values (NSArray).

RestKit: How to POST a NSManagedObject as JSON without any nesting attributes?

This should be a really easy one, but sadly I haven't found any answer...
What RestKit mapped my object to:
request.body={"user":{"pass":"1234","id":0,"login":"awesome_guy","tier":0}}
What I really want:
{"pass":"1234","id":0,"login":"awesome_guy","tier":0}
Just without the object name "user".
If you have dealt with this issue, it'll take you 5 seconds to answer. If you haven't used RestKit. You do not know the answer. I'm attaching my code anyway:
User Object Mapping:
/* ===========================
* ====User Object Mapping====
* ==========================*/
RKEntityMapping* userObjectMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([User class]) inManagedObjectStore:objectManager.managedObjectStore];
NSDictionary *userObjectMappingDict = #{
#"id":#"id",
#"login":#"login",
#"firstName":#"firstName",
#"lastName":#"lastName",
#"phoneNumber":#"phoneNumber",
#"email":#"email",
#"tier":#"tier",
#"sessionId":#"sessionId",
#"pass":#"password"
};
userObjectMapping.identificationAttributes = #[#"id"];
[userObjectMapping addAttributeMappingsFromDictionary:userObjectMappingDict];
RKEntityMapping* userBusinessMapping = [RKEntityMapping mappingForEntityForName:#"Business" inManagedObjectStore:objectManager.managedObjectStore];
[userBusinessMapping addAttributeMappingsFromDictionary:#{#"business":#"id"}]; // Nil Key path
[userObjectMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:nil toKeyPath:#"business" withMapping:userBusinessMapping]];
You should have an instance of RKRequestDescriptor that you haven't shown. It's created with requestDescriptorWithMapping:objectClass:rootKeyPath:. You have the root key path set to #"user" and you should set it to nil.

Right way to serialize nested collection with RestKit

I'm using RestKit to POST my Album class with his nested collection o songs (Song class)
I cannot find the right way to serialize the NSArray containing album songs: it serialize the whole collection into a kind of collection of NSDictionary.
I'm using v 0.10.0 and using NSObjects not CoreData
Here is my json structure:
{"album":
{"id":12,
"source":"apple",
"collection_name":"The Platinum Collection",
"artist_name":"Queen",
"collection_id":"28007467",
"genre_id":5,
"thumb":"mythumburl.jpg",
"creation_user_id":1,
"songs":[
{"id":16,
"track_name":"Bohemian Rhapsody",
"track_time_millis":353933,
"disc_number":1,
"track_number":1,
"track_time":"00:05:53"},
...
]
}
This is my actual mapping:
RKObjectMapping *songMapping = [RKObjectMapping mappingForClass:[Song class]];
[songMapping mapKeyPath:#"id" toAttribute:#"code"];
[songMapping mapKeyPath:#"source" toAttribute:#"source"];
[songMapping mapKeyPath:#"album_id" toAttribute:#"album_id"];
[songMapping mapKeyPath:#"track_name" toAttribute:#"track_name"];
[songMapping mapKeyPath:#"track_time_millis" toAttribute:#"track_time_millis"];
[songMapping mapKeyPath:#"track_time" toAttribute:#"track_time"];
[songMapping mapKeyPath:#"disc_number" toAttribute:#"disc_number"];
[songMapping mapKeyPath:#"track_number" toAttribute:#"track_number"];
[songMapping mapKeyPath:#"preview_url" toAttribute:#"preview_url"];
[objectManager.mappingProvider setObjectMapping:songMapping forKeyPath:#"song"];
[objectManager.mappingProvider setSerializationMapping:[songMapping inverseMapping] forClass:[Song class]];
RKObjectMapping *albumMapping = [RKObjectMapping mappingForClass:[Album class]];
...
[albumMapping hasMany:#"songs" withMapping:songMapping];
// Setup our object mappings
[objectManager.mappingProvider setObjectMapping:albumMapping forKeyPath:#"album"];
[objectManager.mappingProvider setSerializationMapping:[albumMapping inverseMapping] forClass:[Album class]];

How to map a JSON array with RestKit

I have json string like this format :
[{"image":"/0001.jpg","link":"/index.php"},
{"image":"/0001.jpg","link":"/index.php"}]
it does not have a key in the top level.
[mapping mapKeyPath:#"image" toAttribute:#"image"];
mapping like this won't work , it give me the error:
restkit.object_mapping:RKObjectMapper.m:81 Adding mapping error: Could not find an object mapping for keyPath: ''
How to map this type of json ?
Use
[[RKObjectManager sharedManager].mappingProvider addObjectMapping:myObject];
You should check "Mapping without KVC" section on Restkit Object Mapping Docs.
Here is an example from the docs:
[
{ "title": "RestKit Object Mapping Intro",
"body": "This article details how to use RestKit object mapping...",
"author": {
"name": "Blake Watters",
"email": "blake#restkit.org"
},
"publication_date": "7/4/2011"
}
]
And you map that like this:
// Our familiar articlesMapping from earlier
RKObjectMapping* articleMapping = [RKObjectMapping mappingForClass:[Article class]];
[articleMapping mapKeyPath:#"title" toAttribute:#"title"];
[articleMapping mapKeyPath:#"body" toAttribute:#"body"];
[articleMapping mapKeyPath:#"author" toAttribute:#"author"];
[articleMapping mapKeyPath:#"publication_date" toAttribute:#"publicationDate"];
[[RKObjectManager sharedManager].mappingProvider addObjectMapping:articleMapping];
For me the solution was:
add this response descriptor, use the object inside de array
[manager addResponseDescriptor:[ObjectInsideTheArray getResponseDescriptor]];
and in the success response
NSArray *response = (NSArray *)[mappingResult array]; //instead of firstObject

Resources