Permalink
Browse files

Add support and test for inversing a mapping containing attributes ma…

…pped with nil destination key paths. fixes #1116
  • Loading branch information...
1 parent 5a20e54 commit b23ea410a8789e48c61faed3aecb07d7f3142651 @blakewatters blakewatters committed Dec 30, 2012
@@ -29,7 +29,7 @@ @implementation RKAttributeMapping
+ (instancetype)attributeMappingFromKeyPath:(NSString *)sourceKeyPath toKeyPath:(NSString *)destinationKeyPath
{
- NSParameterAssert(destinationKeyPath);
+ NSAssert(sourceKeyPath || destinationKeyPath, @"Both the source and destination key paths cannot be nil");
RKAttributeMapping *attributeMapping = [self new];
attributeMapping.sourceKeyPath = sourceKeyPath;
attributeMapping.destinationKeyPath = destinationKeyPath;
@@ -71,6 +71,8 @@ id RKTransformedValueWithClass(id value, Class destinationType, NSValueTransform
if ([value isKindOfClass:destinationType]) {
// No transformation necessary
return value;
+ } else if ([destinationType isSubclassOfClass:[NSDictionary class]]) {
+ return [NSMutableDictionary dictionaryWithObject:[NSMutableDictionary dictionary] forKey:value];
} else if (RKClassIsCollection(destinationType) && !RKObjectIsCollection(value)) {
// Call ourself recursively with an array value to transform as appropriate
return RKTransformedValueWithClass(@[ value ], destinationType, dateToStringValueTransformer);
@@ -187,6 +189,15 @@ static id RKPrimitiveValueForNilValueOfClass(Class keyValueCodingClass)
return nestedMappings;
}
+static void RKSetValueForObject(id value, id destinationObject)
+{
+ if ([destinationObject isKindOfClass:[NSMutableDictionary class]] && [value isKindOfClass:[NSDictionary class]]) {
+ [destinationObject setDictionary:value];
+ } else {
+ [NSException raise:NSInvalidArgumentException format:@"Unable to set value for destination object of type '%@': no strategy available. %@ to %@", [destinationObject class], value, destinationObject];
+ }
+}
+
@interface RKMappingOperation ()
@property (nonatomic, strong, readwrite) RKMapping *mapping;
@property (nonatomic, strong, readwrite) id sourceObject;
@@ -369,7 +380,11 @@ - (void)applyAttributeMapping:(RKAttributeMapping *)attributeMapping withValue:(
if ([self shouldSetValue:&value atKeyPath:attributeMapping.destinationKeyPath]) {
RKLogTrace(@"Mapped attribute value from keyPath '%@' to '%@'. Value: %@", attributeMapping.sourceKeyPath, attributeMapping.destinationKeyPath, value);
- [self.destinationObject setValue:value forKeyPath:attributeMapping.destinationKeyPath];
+ if (attributeMapping.destinationKeyPath) {
+ [self.destinationObject setValue:value forKeyPath:attributeMapping.destinationKeyPath];
+ } else {
+ RKSetValueForObject(value, self.destinationObject);
+ }
if ([self.delegate respondsToSelector:@selector(mappingOperation:didSetValue:forKeyPath:usingMapping:)]) {
[self.delegate mappingOperation:self didSetValue:value forKeyPath:attributeMapping.destinationKeyPath usingMapping:attributeMapping];
}
@@ -7,6 +7,8 @@
//
#import "RKTestEnvironment.h"
+#import "RKTestUser.h"
+#import "RKObjectMappingOperationDataSource.h"
@interface RKObjectMappingTest : RKTestCase
@@ -233,4 +235,23 @@ - (void)testBreakageOfRecursiveInverseCyclicGraphs
expect([inverseMapping propertyMappingsBySourceKeyPath][@"children"]).notTo.beNil();
}
+- (void)testInverseMappingWithNilDestinationKeyPathForAttributeMapping
+{
+ // Map @"Blake" to RKTestUser with name = @"Blake"
+ RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
+ [mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:@"name"]];
+
+ RKObjectMapping *inverseMapping = [mapping inverseMapping];
+
+ RKTestUser *user = [RKTestUser new];
+ user.name = @"Blake";
+ NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
+ RKMappingOperation *operation = [[RKMappingOperation alloc] initWithSourceObject:user destinationObject:dictionary mapping:inverseMapping];
+ RKObjectMappingOperationDataSource *dataSource = [RKObjectMappingOperationDataSource new];
+ operation.dataSource = dataSource;
+ [operation start];
+
+ expect(operation.destinationObject).to.equal(@{ @"Blake": @{} });
+}
+
@end

0 comments on commit b23ea41

Please sign in to comment.