diff --git a/Code/ObjectMapping/RKObjectMapping.m b/Code/ObjectMapping/RKObjectMapping.m index 6003dbbe..2a569eb5 100644 --- a/Code/ObjectMapping/RKObjectMapping.m +++ b/Code/ObjectMapping/RKObjectMapping.m @@ -157,6 +157,7 @@ NSDate *RKDateFromStringWithFormatters(NSString *dateString, NSArray *formatters - (void)addPropertyMappingsFromArray:(NSArray *)arrayOfPropertyMappings { + NSAssert([[arrayOfPropertyMappings valueForKeyPath:@"@distinctUnionOfObjects.objectMapping"] count] == 0, @"One or more of the property mappings in the given array has already been added to another `RKObjectMapping` object. You probably want to obtain a copy of the array of mappings: `[[NSArray alloc] initWithArray:arrayOfPropertyMappings copyItems:YES]`"); for (RKPropertyMapping *propertyMapping in arrayOfPropertyMappings) { [self addPropertyMapping:propertyMapping]; } @@ -204,16 +205,19 @@ NSDate *RKDateFromStringWithFormatters(NSString *dateString, NSArray *formatters - (void)addAttributeMappingsFromArray:(NSArray *)arrayOfAttributeNamesOrMappings { + NSMutableArray *arrayOfAttributeMappings = [NSMutableArray arrayWithCapacity:[arrayOfAttributeNamesOrMappings count]]; for (id entry in arrayOfAttributeNamesOrMappings) { if ([entry isKindOfClass:[NSString class]]) { - [self addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:entry toKeyPath:entry]]; + [arrayOfAttributeMappings addObject:[RKAttributeMapping attributeMappingFromKeyPath:entry toKeyPath:entry]]; } else if ([entry isKindOfClass:[RKAttributeMapping class]]) { - [self addPropertyMapping:entry]; + [arrayOfAttributeMappings addObject:entry]; } else { [NSException raise:NSInvalidArgumentException format:@"*** - [%@ %@]: Unable to attribute mapping from unsupported entry of type '%@' (%@).", NSStringFromClass([self class]), NSStringFromSelector(_cmd), NSStringFromClass([entry class]), entry]; } } + + [self addPropertyMappingsFromArray:arrayOfAttributeMappings]; } - (void)removePropertyMapping:(RKPropertyMapping *)attributeOrRelationshipMapping diff --git a/Tests/Logic/ObjectMapping/RKObjectMappingTest.m b/Tests/Logic/ObjectMapping/RKObjectMappingTest.m index 61efb06c..a2e65a42 100644 --- a/Tests/Logic/ObjectMapping/RKObjectMappingTest.m +++ b/Tests/Logic/ObjectMapping/RKObjectMappingTest.m @@ -105,4 +105,64 @@ assertThatBool([mapping1 isEqualToMapping:mapping2], is(equalToBool(NO))); } +- (void)testThatAddingAPropertyMappingThatExistsInAnotherMappingTriggersException +{ + RKObjectMapping *firstMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]]; + RKAttributeMapping *attributeMapping = [RKAttributeMapping attributeMappingFromKeyPath:@"this" toKeyPath:@"that"]; + [firstMapping addPropertyMapping:attributeMapping]; + + RKObjectMapping *secondMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]]; + NSException *exception = nil; + @try { + [secondMapping addPropertyMapping:attributeMapping]; + } + @catch (NSException *caughtException) { + exception = caughtException; + } + @finally { + expect(exception).notTo.beNil(); + expect(exception.reason).to.equal(@"Cannot add a property mapping object that has already been added to another `RKObjectMapping` object. You probably want to obtain a copy of the mapping: `[propertyMapping copy]`"); + } +} + +- (void)testThatAddingAnArrayOfPropertyMappingsThatExistInAnotherMappingTriggersException +{ + RKObjectMapping *firstMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]]; + RKAttributeMapping *attributeMapping = [RKAttributeMapping attributeMappingFromKeyPath:@"this" toKeyPath:@"that"]; + [firstMapping addPropertyMapping:attributeMapping]; + + RKObjectMapping *secondMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]]; + NSException *exception = nil; + @try { + [secondMapping addPropertyMappingsFromArray:@[attributeMapping]]; + } + @catch (NSException *caughtException) { + exception = caughtException; + } + @finally { + expect(exception).notTo.beNil(); + expect(exception.reason).to.equal(@"One or more of the property mappings in the given array has already been added to another `RKObjectMapping` object. You probably want to obtain a copy of the array of mappings: `[[NSArray alloc] initWithArray:arrayOfPropertyMappings copyItems:YES]`"); + } +} + +- (void)testThatAddingAnArrayOfAttributeMappingsThatExistInAnotherMappingTriggersException +{ + RKObjectMapping *firstMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]]; + RKAttributeMapping *attributeMapping = [RKAttributeMapping attributeMappingFromKeyPath:@"this" toKeyPath:@"that"]; + [firstMapping addPropertyMapping:attributeMapping]; + + RKObjectMapping *secondMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]]; + NSException *exception = nil; + @try { + [secondMapping addAttributeMappingsFromArray:@[attributeMapping, @"stringValue"]]; + } + @catch (NSException *caughtException) { + exception = caughtException; + } + @finally { + expect(exception).notTo.beNil(); + expect(exception.reason).to.equal(@"One or more of the property mappings in the given array has already been added to another `RKObjectMapping` object. You probably want to obtain a copy of the array of mappings: `[[NSArray alloc] initWithArray:arrayOfPropertyMappings copyItems:YES]`"); + } +} + @end