Permalink
Browse files

Fix type mismatch assertion in cases where JSON/XML payload contains …

…a string value for an integer primary key. fixes #754
  • Loading branch information...
1 parent 1dc765c commit fa88dd44ef4911b7a21af5c87c5fd0ae7dadc7e6 @blakewatters blakewatters committed May 24, 2012
View
9 Code/CoreData/NSEntityDescription+RKAdditions.h
@@ -81,4 +81,13 @@ extern NSString * const RKEntityDescriptionPrimaryKeyAttributeValuePredicateSubs
*/
- (NSPredicate *)predicateForPrimaryKeyAttributeWithValue:(id)value;
+/**
+ Coerces the given value into the class representing the primary key. Currently support NSString
+ and NSNumber coercsions.
+
+ @bug **NOTE** This API is temporary and will be deprecated and replaced.
+ @since 0.10.1
+ */
+- (id)coerceValueForPrimaryKey:(id)primaryKeyValue;
+
@end
View
15 Code/CoreData/NSEntityDescription+RKAdditions.m
@@ -74,12 +74,12 @@ - (NSPredicate *)predicateForPrimaryKeyAttribute
return (NSPredicate *) objc_getAssociatedObject(self, &primaryKeyPredicateKey);
}
-- (NSPredicate *)predicateForPrimaryKeyAttributeWithValue:(id)value
+- (id)coerceValueForPrimaryKey:(id)primaryKeyValue
{
- id searchValue = value;
+ id searchValue = primaryKeyValue;
Class theClass = [self primaryKeyAttributeClass];
if (theClass) {
- // TODO: This coercsion behave should be pluggable and reused from the mapper
+ // TODO: This coercsion behavior should be pluggable and reused from the mapper
if ([theClass isSubclassOfClass:[NSNumber class]] && ![searchValue isKindOfClass:[NSNumber class]]) {
// Handle NSString -> NSNumber
if ([searchValue isKindOfClass:[NSString class]]) {
@@ -92,7 +92,14 @@ - (NSPredicate *)predicateForPrimaryKeyAttributeWithValue:(id)value
}
}
}
- NSDictionary *variables = [NSDictionary dictionaryWithObject:searchValue
+
+ return searchValue;
+}
+
+- (NSPredicate *)predicateForPrimaryKeyAttributeWithValue:(id)value
+{
+ id substitutionValue = [self coerceValueForPrimaryKey:value];
+ NSDictionary *variables = [NSDictionary dictionaryWithObject:substitutionValue
forKey:RKEntityDescriptionPrimaryKeyAttributeValuePredicateSubstitutionVariable];
return [[self predicateForPrimaryKeyAttribute] predicateWithSubstitutionVariables:variables];
}
View
3 Code/CoreData/RKManagedObjectMapping.m
@@ -182,7 +182,8 @@ - (id)mappableObjectForData:(id)mappableData {
object = [[[NSManagedObject alloc] initWithEntity:entity
insertIntoManagedObjectContext:[_objectStore managedObjectContextForCurrentThread]] autorelease];
if (primaryKeyAttribute && primaryKeyValue && ![primaryKeyValue isEqual:[NSNull null]]) {
- [object setValue:primaryKeyValue forKey:primaryKeyAttribute];
+ id coercedPrimaryKeyValue = [entity coerceValueForPrimaryKey:primaryKeyValue];
+ [object setValue:coercedPrimaryKeyValue forKey:primaryKeyAttribute];
}
if ([self.objectStore.cacheStrategy respondsToSelector:@selector(didCreateObject:)]) {
View
26 Tests/Logic/CoreData/RKManagedObjectMappingTest.m
@@ -317,4 +317,30 @@ - (void)testMappingWithInMemoryCacheWherePrimaryKeyAttributeOfMappingDisagreesWi
assertThat(cachedObject, is(equalTo(human)));
}
+- (void)testThatCreationOfNewObjectWithIncorrectTypeValueForPrimaryKeyAddsToCache
+{
+ RKManagedObjectStore* store = [RKTestFactory managedObjectStore];
+ store.cacheStrategy = [RKInMemoryManagedObjectCache new];
+ [RKHuman truncateAll];
+ RKManagedObjectMapping* mapping = [RKManagedObjectMapping mappingForClass:[RKHuman class] inManagedObjectStore:store];
+ mapping.primaryKeyAttribute = @"railsID";
+ [RKHuman entity].primaryKeyAttributeName = @"railsID";
+ [mapping addAttributeMapping:[RKObjectAttributeMapping mappingFromKeyPath:@"monkey.name" toKeyPath:@"name"]];
+ [mapping addAttributeMapping:[RKObjectAttributeMapping mappingFromKeyPath:@"monkey.railsID" toKeyPath:@"railsID"]];
+
+ [RKHuman truncateAll];
+ RKHuman* human = [RKHuman object];
+ human.name = @"Testing";
+ human.railsID = [NSNumber numberWithInteger:12345];
+ [store save:nil];
+ assertThatBool([RKHuman hasAtLeastOneEntity], is(equalToBool(YES)));
+
+ NSDictionary* data = [NSDictionary dictionaryWithObject:@"12345" forKey:@"railsID"];
+ NSDictionary* nestedDictionary = [NSDictionary dictionaryWithObject:data forKey:@"monkey"];
+ RKHuman *object = [mapping mappableObjectForData:nestedDictionary];
+ assertThat(object, isNot(nilValue()));
+ assertThat(object, is(equalTo(human)));
+ assertThatInteger([object.railsID integerValue], is(equalToInteger(12345)));
+}
+
@end

0 comments on commit fa88dd4

Please sign in to comment.