Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Struggling with RestKit mapping object and references

Here my entities

- HomeArticle
identifier
article (relationship)

- Article
identifier
title
subtitle
text
home (relationship)

I have a payload that looks like this:

[
    {
        "id": "1",
        "title": "A Nice Simple One",
        "subtitle": "Subtitle",
        "text": "text text text"
    },
    {
        "id": "2",
        "title": "A Nice Simple Two",
        "subtitle": "London",
        "text": "text text text"
    }
]

I'm trying to popolate HomeArticle and create the relationship at the same time something like:

RKObjectManager* objectManager = [RKObjectManager sharedManager];
    NSString *pathString = @"/get_news/";
    [objectManager loadObjectsAtResourcePath:pathString usingBlock:^(RKObjectLoader *loader) {
        loader.delegate = self;
        loader.objectMapping = [self myHomeArticleMapping];

        loader.onDidLoadObject = ^(id object) {
            ...
        };
    }];

- (RKManagedObjectMapping *) myHomeArticleMapping{
    if(_homeArticleMapping == nil){
        _homeArticleMapping = [RKManagedObjectMapping mappingForClass:[HomeArticle class] inManagedObjectStore:[[RKObjectManager sharedManager] objectStore]];
        [_homeArticleMapping mapKeyPath:@"id" toAttribute:@"identifier"];
        [_homeArticleMapping mapRelationship:@"article" withMapping:[self myArticleMapping]];
        [_homeArticleMapping connectRelationship:@"article" withObjectForPrimaryKeyAttribute:@"identifier"];
    }
}

- (RKManagedObjectMapping *) myArticleMapping{
    if(_articleMapping == nil){
        _articleMapping = [RKManagedObjectMapping mappingForClass:[Article class] inManagedObjectStore:[[RKObjectManager sharedManager] objectStore]];

        [_articleMapping mapKeyPath:@"id" toAttribute:@"identifier"];
        [_articleMapping mapKeyPath:@"title" toAttribute:@"title"];
        [_articleMapping mapKeyPath:@"subtitle" toAttribute:@"subtitle"];
        [_articleMapping mapKeyPath:@"text" toAttribute:@"text"];
    }
}

The identifier for "HomeArticle" is populated but the relationship is not created. Do you have any idea how I can achieve this? The project I'm working on is bit more complex, but I simplified it to make it bit more clear.

Workaround

Ok, the only way I managed to make this work was to re-work the payload in the method:

- (void)objectLoader:(RKObjectLoader*)loader willMapData:(inout id *)mappableData

I basically created a Dictionary out of the payload Array giving the id as key:

- (void)objectLoader:(RKObjectLoader*)loader willMapData:(inout id *)mappableData {
    NSMutableArray *newsArray = [NSMutableArray arrayWithArray:(NSArray *)*mappableData];
    NSMutableDictionary *newData = [[NSMutableDictionary alloc] init];
    int elementNumber = [newsArray count];
    for(int i = 0 ; i < elementNumber ; i++){
        NSMutableDictionary *news = [NSMutableDictionary dictionaryWithDictionary:[newsArray objectAtIndex:i]];

        [newData setObject:news forKey:[news objectForKey:@"id"]];
    }
    *mappableData = newData;
}

end then I changed the mapping of the "HomeArticle" like this:

if(_homeArticleMapping == nil){
            _homeArticleMapping = [RKManagedObjectMapping mappingForClass:[HomeArticle class] inManagedObjectStore:[[RKObjectManager sharedManager] objectStore]];
        _homeArticleMapping.forceCollectionMapping = YES;
        [_homeArticleMapping mapKeyOfNestedDictionaryToAttribute:@"identifier"];
        _homeArticleMapping.primaryKeyAttribute = @"identifier";
        [_homeArticleMapping mapKeyPath:@"(identifier)"
                         toRelationship:@"article"
                            withMapping:[self myArticleMapping]];
 }

it works but I don't really like it.

like image 689
SQu Avatar asked Oct 03 '12 17:10

SQu


1 Answers

Say I had a Entity with an opponent relationship. I would want to map the relationship with another mapping called facebookMapping. Then add the mapping to the mappingProvider at the respective keyPath ( or root name).

RKManagedObjectMapping *gameEntryMapping = [RKManagedObjectMapping mappingForClass:[GameEntry class] inManagedObjectStore:[RKObjectManager sharedManager].objectStore];
RKManagedObjectMapping *facebookMapping = [RKManagedObjectMapping mappingForClass:[FacebookUser class] inManagedObjectStore:[RKObjectManager sharedManager].objectStore];
[gameEntryMapping mapRelationship:@"opponent" withMapping:facebookMapping];
[facebookMapping mapKeyPath:@"systemID" toAttribute:@"systemId"];
[facebookMapping mapKeyPath:@"name" toAttribute:@"name"];
[[RKObjectManager sharedManager].mappingProvider setMapping:gameEntryMapping forKeyPath:@"games"];
[[RKObjectManager sharedManager].mappingProvider addObjectMapping:gameEntryMapping];
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:@"/syncGames" usingBlock:^(RKObjectLoader *loader) {
    loader.method = RKRequestMethodPOST;
    loader.params = params;
    loader.delegate = self;
}];
like image 65
RyanCodes Avatar answered Oct 18 '22 09:10

RyanCodes