0
votes

I used Restkit 0.20 (first time) for posting objects to a Rails server via JSON, and I 've been stuck for the last days with an annoying mapping error. Got 2 objects Picture and Item.

Picture
{
"base64" : null,
"id" : 1,
"created_at" : "2013-08-28T15:08:49Z",
"user_nickname" : "user_name",
"tag" : "ALPHA",
"nbitems" : null,
"path" : {
  "url" : "https://www.mywebsite/pictures/1/default.jpg"
},
"updated_at" : "2013-08-28T15:08:49Z",
"user_id" : 1
}


Item
{
"base64" : null,
"picture_id" : 1,
"id" : 1,
"created_at" : "2013-08-28T15:10:54Z",
"itemurl" : {
  "url" : "https://www.mywebsite/pictures/1/item1.png"
},
"nickname" : "",
"user_id" : 1,
"updated_at" : "2013-08-28T15:10:54Z"
}

Here's my mapping in the AppDelegate.m

    //Mapping users
RKEntityMapping *userMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([User class]) inManagedObjectStore:manager.managedObjectStore];
[userMapping addAttributeMappingsFromDictionary:@{
 @"id" : @"user_id",
 @"email" : @"email",
 @"nickname" : @"nickname",
 @"created_at" : @"createdAt"
 }];
userMapping.identificationAttributes = @[ @"user_id" ];


//Mapping paths
RKEntityMapping *pathMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([Path class]) inManagedObjectStore:manager.managedObjectStore];
[pathMapping addAttributeMappingsFromDictionary:@{
 @"url" : @"url"
 }];

//Mapping itemURL
RKEntityMapping *itemURLMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([ItemURL class]) inManagedObjectStore:manager.managedObjectStore];
[pathMapping addAttributeMappingsFromDictionary:@{
 @"url" : @"url"
 }];


//Mapping pictures
RKEntityMapping *pictureMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([Picture class]) inManagedObjectStore:managedObjectStore];
[pictureMapping addAttributeMappingsFromDictionary:@{
 @"id" : @"picture_id",
 @"user_id" : @"user_id",
 @"user_nickname" : @"user_nickname",
 @"nbitems" : @"nbitems",
 @"tag" : @"tag",
 @"base64" : @"base64",  
 @"created_at" : @"createdAt"
 }];
pictureMapping.identificationAttributes = @[ @"picture_id"];
[pictureMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"path" toKeyPath:@"path" withMapping:pathMapping]];

[manager addResponseDescriptorsFromArray:@[
[RKResponseDescriptor responseDescriptorWithMapping:pictureMapping
                                         pathPattern:@"pictures"
                                         keyPath:nil
                                         statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]
 ]];

RKObjectMapping *pictureRequestMapping = [RKObjectMapping requestMapping];
[pictureRequestMapping addAttributeMappingsFromArray:@[@"user_id", @"user_nickname", @"tag", @"base64", @"path"]];
RKRequestDescriptor *pictureRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:pictureRequestMapping objectClass:[Picture class] rootKeyPath:@"picture" method:RKRequestMethodAny];
[manager addRequestDescriptor:pictureRequestDescriptor];


//Mapping items
RKEntityMapping *itemMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([Item class]) inManagedObjectStore:managedObjectStore];
itemMapping.identificationAttributes = @[ @"item_id"];
[itemMapping addAttributeMappingsFromDictionary:@{
 @"id" : @"item_id",
 @"picture_id" : @"picture_id",
 @"user_id" : @"user_id",
 @"nickname" : @"nickname",
 @"base64" : @"base64",
 @"created_at" : @"createdAt"
 }];
RKRelationshipMapping *itemURLRelation = [RKRelationshipMapping relationshipMappingFromKeyPath:@"itemurl" toKeyPath:@"itemurl" withMapping:itemURLMapping];
[itemMapping addPropertyMapping:itemURLRelation];

RKResponseDescriptor *itemDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:itemMapping
                                         pathPattern:@"items"
                                             keyPath:nil
                                         statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[manager addResponseDescriptor:itemDescriptor];

RKObjectMapping *itemRequestMapping = [RKObjectMapping requestMapping];
[itemRequestMapping addAttributeMappingsFromArray:@[@"picture_id", @"user_id", @"nickname", @"base64", @"itemurl"]];
RKRequestDescriptor *itemRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:itemRequestMapping objectClass:[Item class] rootKeyPath:@"item" method:RKRequestMethodAny];
[manager addRequestDescriptor:itemRequestDescriptor];

I post a Picture instance in a ViewController and it works perfectly

    - (void)uploadPicture:(UIImage *)chosenImage{
    NSManagedObjectContext *moc = [RKManagedObjectStore defaultStore].mainQueueManagedObjectContext;
UIImage *resizedImage = [self scaleImage:chosenImage maxWidth:640 maxHeight:960];
NSString *imageEncoded = [self image2jpg2String:resizedImage];

Picture *picture = [Picture insertInManagedObjectContext:moc];
picture.user_id = userId;
picture.user_nickname = @"user_nickname";
picture.tag = @"ALPHA";
picture.base64 = imageEncoded;

[[RKObjectManager sharedManager] postObject:picture path:@"pictures" parameters:nil success:nil failure:^(RKObjectRequestOperation *operation, NSError *error) { NSLog(@"Error: %@",error);}];
    }

I try to do the same with an Item instance in another controller

    - (void)uploadItem{
    NSManagedObjectContext *mocFVC = [RKManagedObjectStore defaultStore].mainQueueManagedObjectContext;
NSNumber *userId = [NSNumber numberWithInt:1];
UIImage *itemImage = self.itemImage.image;
UIImage *resizedItem = [self scaleImage:itemImage maxWidth:640 maxHeight:960];
NSString *itemEncoded = [self image2png2String:resizedItem];

Item *item = [Item insertInManagedObjectContext:mocFVC];
item.user_id = userId;
item.nickname = @"user_nickname";
item.picture_id = pictureToDisplay.picture_id;
item.base64 = itemEncoded;

[[RKObjectManager sharedManager] postObject:item path:@"items" parameters:nil success:nil failure:^(RKObjectRequestOperation *operation, NSError *error) { NSLog(@"Error: %@",error);}];    
    }

But unless I comment the item.base64, xcode always returns the following error

    2013-08-28 22:51:41.116 MYPROJECT[4588:1603] E restkit.network:RKObjectRequestOperation.m:243 POST 'http://www.mywebsite/items' (422 Unprocessable Entity / 0 objects) [request=0.6791s mapping=0.0000s total=0.7111s]: Error Domain=org.restkit.RestKit.ErrorDomain Code=1001 "No mappable object representations were found at the key paths searched." 
    UserInfo=0x1e8af330 {DetailedErrors=(), NSLocalizedFailureReason=The mapping operation was unable to find any nested object representations at the key paths searched: error
    The representation inputted to the mapper was found to contain nested object representations at the following key paths: itemurl

    This likely indicates that you have misconfigured the key paths for your mappings., NSLocalizedDescription=No mappable object representations were found at the key paths searched., keyPath=null}

    2013-08-28 22:51:41.119 MYPROJECT[4588:907] Error: Error Domain=org.restkit.RestKit.ErrorDomain Code=1001 "No mappable object representations were found at the key paths searched." UserInfo=0x1e8af330 {DetailedErrors=(), NSLocalizedFailureReason=The mapping operation was unable to find any nested object representations at the key paths searched: error

    The representation inputted to the mapper was found to contain nested object representations at the following key paths: itemurl

    This likely indicates that you have misconfigured the key paths for your mappings., NSLocalizedDescription=No mappable object representations were found at the key paths searched., keyPath=null}

I checked a lot of post on stackoverflow and read the restkit doc before posting, but don't understand why it doesn't work for my item since it's code and picture model are very closed to the one I use for my Item class. Am I missing something ? Any idea ? :)

1
Have you checked what actually hits the wire and what happens on the server? The message you see indicates the server is throwing an error back.Wain

1 Answers

0
votes

@Wain the logs didn't show anything

Turns out the Restkit part was correct. The error was happening in my base64/upload function in the model.

    def base64=(data)
# decode data and create stream on them
filename = "#{self.user_id}.png"
io = CarrierStringIO.new(filename, Base64.decode64(data))

# this will do the thing (photo is mounted carrierwave uploader)
self.path = io
end

The filename line works in a webbrowser but not using JSON. #weird Had to change the path of the file to keep the user_id as data