Added support for object mapping a single object instance onto an NSOrderedSet collection. fixes #616

This commit is contained in:
Blake Watters
2012-03-30 09:29:41 -04:00
parent 0e498ad326
commit 73fe4f1237
2 changed files with 37 additions and 6 deletions

View File

@@ -404,8 +404,15 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue) {
return appliedMappings;
}
- (BOOL)isTypeACollection:(Class)type {
Class orderedSetClass = NSClassFromString(@"NSOrderedSet");
return (type && ([type isSubclassOfClass:[NSSet class]] ||
[type isSubclassOfClass:[NSArray class]] ||
(orderedSetClass && [type isSubclassOfClass:orderedSetClass])));
}
- (BOOL)isValueACollection:(id)value {
return ([value isKindOfClass:[NSSet class]] || [value isKindOfClass:[NSArray class]]);
return [self isTypeACollection:[value class]];
}
- (BOOL)mapNestedObject:(id)anObject toObject:(id)anotherObject withRealtionshipMapping:(RKObjectRelationshipMapping*)relationshipMapping {
@@ -474,15 +481,17 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue) {
}
// Handle case where incoming content is a single object, but we want a collection
Class relationshipType = [self.objectMapping classForProperty:relationshipMapping.destinationKeyPath];
BOOL mappingToCollection = (relationshipType &&
([relationshipType isSubclassOfClass:[NSSet class]] || [relationshipType isSubclassOfClass:[NSArray class]]));
Class relationshipType = [self.objectMapping classForProperty:relationshipMapping.destinationKeyPath];
BOOL mappingToCollection = [self isTypeACollection:relationshipType];
if (mappingToCollection && ![self isValueACollection:value]) {
Class orderedSetClass = NSClassFromString(@"NSOrderedSet");
RKLogDebug(@"Asked to map a single object into a collection relationship. Transforming to an instance of: %@", NSStringFromClass(relationshipType));
if ([relationshipType isSubclassOfClass:[NSArray class]]) {
value = [relationshipType arrayWithObject:value];
} else if ([relationshipType isSubclassOfClass:[NSSet class]]) {
value = [relationshipType setWithObject:value];
} else if (orderedSetClass && [relationshipType isSubclassOfClass:orderedSetClass]) {
value = [relationshipType orderedSetWithObject:value];
} else {
RKLogWarning(@"Failed to transform single object");
}
@@ -530,7 +539,7 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue) {
// If the relationship has changed, set it
if ([self shouldSetValue:&destinationObject atKeyPath:relationshipMapping.destinationKeyPath]) {
Class managedObjectClass = NSClassFromString(@"NSManagedObject");
Class nsOrderSetClass = NSClassFromString(@"NSOrderedSet");
Class nsOrderedSetClass = NSClassFromString(@"NSOrderedSet");
if (managedObjectClass && [self.destinationObject isKindOfClass:managedObjectClass]) {
RKLogTrace(@"Found a managedObject collection. About to apply value via mutable[Set|Array]ValueForKey");
if ([destinationObject isKindOfClass:[NSSet class]]) {
@@ -541,7 +550,7 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue) {
RKLogTrace(@"Mapped NSArray relationship object from keyPath '%@' to '%@'. Value: %@", relationshipMapping.sourceKeyPath, relationshipMapping.destinationKeyPath, destinationObject);
NSMutableArray* destinationArray = [self.destinationObject mutableArrayValueForKey:relationshipMapping.destinationKeyPath];
[destinationArray setArray:destinationObject];
} else if (nsOrderSetClass && [destinationObject isKindOfClass:nsOrderSetClass]) {
} else if (nsOrderedSetClass && [destinationObject isKindOfClass:nsOrderedSetClass]) {
RKLogTrace(@"Mapped NSOrderedSet relationship object from keyPath '%@' to '%@'. Value: %@", relationshipMapping.sourceKeyPath, relationshipMapping.destinationKeyPath, destinationObject);
[self.destinationObject setValue:destinationObject forKey:relationshipMapping.destinationKeyPath];
}

View File

@@ -1216,6 +1216,28 @@
assertThatUnsignedInteger([user.friends count], is(equalToInt(1)));
}
- (void)testShouldMapANestedObjectToOrderedSetCollection {
RKObjectMapping* userMapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
RKObjectAttributeMapping* nameMapping = [RKObjectAttributeMapping mappingFromKeyPath:@"name" toKeyPath:@"name"];
[userMapping addAttributeMapping:nameMapping];
RKObjectMapping* addressMapping = [RKObjectMapping mappingForClass:[RKTestAddress class]];
RKObjectAttributeMapping* cityMapping = [RKObjectAttributeMapping mappingFromKeyPath:@"city" toKeyPath:@"city"];
[addressMapping addAttributeMapping:cityMapping];
RKObjectRelationshipMapping* hasOneMapping = [RKObjectRelationshipMapping mappingFromKeyPath:@"address" toKeyPath:@"friendsOrderedSet" withMapping:addressMapping];
[userMapping addRelationshipMapping:hasOneMapping];
RKObjectMapper* mapper = [RKObjectMapper new];
id userInfo = [RKTestFixture parsedObjectWithContentsOfFixture:@"user.json"];
RKTestUser* user = [RKTestUser user];
BOOL success = [mapper mapFromObject:userInfo toObject:user atKeyPath:@"" usingMapping:userMapping];
[mapper release];
assertThatBool(success, is(equalToBool(YES)));
assertThat(user.name, is(equalTo(@"Blake Watters")));
assertThat(user.friendsOrderedSet, isNot(nilValue()));
assertThatUnsignedInteger([user.friendsOrderedSet count], is(equalToInt(1)));
}
- (void)testShouldMapANestedObjectCollection {
RKObjectMapping* userMapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
RKObjectAttributeMapping* nameMapping = [RKObjectAttributeMapping mappingFromKeyPath:@"name" toKeyPath:@"name"];