* Implemented relation mapping in RKDynamicRouter

* Added specs covering the functionality
This commit is contained in:
Andras Hatvani
2011-05-04 12:27:50 +02:00
parent 2c6f8ff8e9
commit d6d92fc6d4
3 changed files with 179 additions and 2 deletions

View File

@@ -100,8 +100,72 @@
return nil;
}
// By default return a form encoded serializable dictionary
return [object propertiesForSerialization];
// set up dictionary containers
NSDictionary* elementsAndProperties = [object propertiesForSerialization];
NSDictionary* relationships = [object relationshipsForSerialization];
int propertyCount = [elementsAndProperties count];
int relationshipCount = [relationships count];
int entryCount = propertyCount + relationshipCount;
NSMutableDictionary* resourceParams = [NSMutableDictionary dictionaryWithCapacity:entryCount];
// add elements and properties
for (NSString* elementName in [elementsAndProperties allKeys]) {
id value = [elementsAndProperties valueForKey:elementName];
NSString* attributeName = [elementName stringByReplacingOccurrencesOfString:@"-" withString:@"_"];
if (![attributeName isEqualToString:@"id"]) {
NSString* keyName = [NSString stringWithFormat:@"%@", attributeName];
[resourceParams setValue:value forKey:keyName];
}
}
void (^handlePrimaryKey)(Class, NSMutableDictionary *, id) = ^(Class blockClass, NSMutableDictionary *attributes, id object) {
if ([blockClass respondsToSelector:@selector(primaryKeyProperty)]) {
NSString *primaryKey = [blockClass performSelector:@selector(primaryKeyProperty)];
id primaryKeyValue = [object valueForKey:primaryKey];
NSString* primaryKeyValueString = [NSString stringWithFormat:@"%@", primaryKeyValue];
// Primary key value isn't defined
if (primaryKeyValue == nil || [primaryKeyValueString isEqualToString:@"0"]) {
// Exclude id
[attributes removeObjectForKey:@"id"];
}
}
};
// add nested relationships
for (NSString* elementName in [relationships allKeys]) {
NSObject *relationship = [relationships objectForKey:elementName];
NSString *relationshipPath = [NSString stringWithFormat:@"%@", elementName];
// to-many relation
if ([relationship isKindOfClass:[NSArray class]] ||
[relationship isKindOfClass:[NSSet class]]) {
NSMutableArray *children = [NSMutableArray array];
for (id child in (NSEnumerator *)relationship) {
Class class = [child class];
NSMutableDictionary* childAttributes = [RKObjectMappableGetPropertiesByElement(child) mutableCopy];
handlePrimaryKey(class, childAttributes, child);
[children addObject:[NSDictionary dictionaryWithDictionary:childAttributes]];
}
[resourceParams setValue:children
forKey:relationshipPath];
// to-one relation
} else {
Class class = [relationship class];
NSMutableDictionary* childAttributes = [RKObjectMappableGetPropertiesByElement(relationship) mutableCopy];
handlePrimaryKey(class, childAttributes, relationship);
[resourceParams setValue:childAttributes
forKey:relationshipPath];
}
}
return resourceParams;
}
@end

View File

@@ -41,4 +41,14 @@
return @"railsID";
}
+ (NSDictionary*)elementToRelationshipMappings {
return [NSDictionary dictionaryWithObjectsAndKeys:
@"human", @"human",
nil];
}
+ (NSArray*)relationshipsToSerialize {
return [NSArray arrayWithObject:@"human"];
}
@end

View File

@@ -9,6 +9,7 @@
#import "RKSpecEnvironment.h"
#import "RKManagedObjectStore.h"
#import "RKHuman.h"
#import "RKCat.h"
@interface RKDynamicRouterSpec : NSObject <UISpec> {
}
@@ -110,4 +111,106 @@
[expectThat(resourcePath) should:be(@"/this/is/the/path")];
}
- (void)itShouldSerializeToOneRelationWithoutId
{
RKDynamicRouter* router = [[[RKDynamicRouter alloc] init] autorelease];
RKHuman* human = [[RKHuman object] autorelease];
RKCat* cat = [[RKCat object] autorelease];
cat.name = @"Cat";
human.name = @"Owner";
cat.human = human;
NSDictionary* serialization = (NSDictionary*) [router serializationForObject:cat method:RKRequestMethodPOST];
NSDictionary* serializedRelation = [serialization objectForKey:@"human"];
[expectThat([serializedRelation objectForKey:@"name"]) should:be(@"Owner")];
}
- (void)itShouldSerializeToOneRelationWithId
{
RKDynamicRouter* router = [[[RKDynamicRouter alloc] init] autorelease];
RKHuman* human = [[RKHuman object] autorelease];
RKCat* cat = [[RKCat object] autorelease];
cat.name = @"Cat";
human.railsID = [NSNumber numberWithInt:1];
human.name = @"Owner";
cat.human = human;
NSDictionary* serialization = (NSDictionary*) [router serializationForObject:cat method:RKRequestMethodPOST];
NSDictionary* serializedRelation = [serialization objectForKey:@"human"];
[expectThat([serializedRelation objectForKey:@"name"]) should:be(@"Owner")];
}
- (void)itShouldSerializeToManyRelationWithoutId
{
RKDynamicRouter* router = [[[RKDynamicRouter alloc] init] autorelease];
RKHuman* human = [[RKHuman object] autorelease];
human.name = @"Owner";
RKCat* cat1 = [[RKCat object] autorelease];
cat1.name = @"Cat1";
[human addCatsObject:cat1];
RKCat* cat2 = [[RKCat object] autorelease];
cat2.name = @"Cat2";
[human addCatsObject:cat2];
NSDictionary* serialization = (NSDictionary*) [router serializationForObject:human method:RKRequestMethodPOST];
NSArray* serializedCats = [serialization objectForKey:@"cats"];
NSDictionary *serCat1 = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:0], @"age",
[NSNumber numberWithInt:0], @"birth_year",
@"Cat1", @"name",
nil];
NSDictionary *serCat2 = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:0], @"age",
[NSNumber numberWithInt:0], @"birth_year",
@"Cat2", @"name",
nil];
[expectThat([serializedCats count]) should:be(2)];
[expectThat([serializedCats containsObject:serCat1]) should:be(TRUE)];
[expectThat([serializedCats containsObject:serCat2]) should:be(TRUE)];
}
- (void)itShouldSerializeToManyRelationWithId
{
RKDynamicRouter* router = [[[RKDynamicRouter alloc] init] autorelease];
RKHuman* human = [[RKHuman object] autorelease];
human.name = @"Owner";
RKCat* cat1 = [[RKCat object] autorelease];
cat1.name = @"Cat1";
cat1.railsID = [NSNumber numberWithInt:1];
[human addCatsObject:cat1];
RKCat* cat2 = [[RKCat object] autorelease];
cat2.name = @"Cat2";
cat2.railsID = [NSNumber numberWithInt:2];
[human addCatsObject:cat2];
NSDictionary* serialization = (NSDictionary*) [router serializationForObject:human method:RKRequestMethodPOST];
NSArray* serializedCats = [serialization objectForKey:@"cats"];
NSDictionary *serCat1 = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:0], @"age",
[NSNumber numberWithInt:0], @"birth_year",
[NSNumber numberWithInt:1], @"id",
@"Cat1", @"name",
nil];
NSDictionary *serCat2 = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:0], @"age",
[NSNumber numberWithInt:0], @"birth_year",
[NSNumber numberWithInt:2], @"id",
@"Cat2", @"name",
nil];
[expectThat([serializedCats count]) should:be(2)];
[expectThat([serializedCats containsObject:serCat1]) should:be(TRUE)];
[expectThat([serializedCats containsObject:serCat2]) should:be(TRUE)];
}
@end