diff --git a/Source/Categories/NSManagedObject+MagicalDataImport.m b/Source/Categories/NSManagedObject+MagicalDataImport.m index 60202c8..b71287c 100644 --- a/Source/Categories/NSManagedObject+MagicalDataImport.m +++ b/Source/Categories/NSManagedObject+MagicalDataImport.m @@ -16,8 +16,22 @@ NSString * const kMagicalRecordImportRelationshipMapKey = @"jsonKeyName"; NSString * const kMagicalRecordImportRelationshipPrimaryKey = @"primaryRelationshipKey"; NSString * const kMagicalRecordImportRelationshipTypeKey = @"type"; + @implementation NSManagedObject (NSManagedObject_DataImport) +- (NSCache *) MR_requestCache +{ + static dispatch_once_t pred; + static NSCache *mr_requestCache = nil; + + dispatch_once(&pred, ^{ + mr_requestCache = [[NSCache alloc] init]; + mr_requestCache.name = @"com.magicalpanda.magicalrecord.requestcache"; + mr_requestCache.totalCostLimit = 100; + }); + return mr_requestCache; +} + - (id) MR_attributeValueFromDictionary:(NSDictionary *)jsonData forAttribute:(NSAttributeDescription *)attributeInfo { NSString *attributeName = [attributeInfo name]; @@ -69,7 +83,7 @@ NSString * const kMagicalRecordImportRelationshipTypeKey = @"type"; return relatedObject; } -- (NSManagedObject *) MR_findObjectForRelationship:(NSRelationshipDescription *)relationshipInfo withData:(id)singleRelatedObjectData +- (NSEntityDescription *)MR_targetEntityDescriptionForRelationship:(NSRelationshipDescription *)relationshipInfo { NSEntityDescription *originalDestinationEntity = [relationshipInfo destinationEntity]; NSDictionary *subentities = [originalDestinationEntity subentitiesByName]; @@ -84,10 +98,16 @@ NSString * const kMagicalRecordImportRelationshipTypeKey = @"type"; } else if ([originalDestinationEntity isAbstract] && [subentities count]) { -// NSString *mappedSubentity = [singleRelatedObjectData valueForKey:kMagicalRecordImportRelationshipTypeKey]; -// [subentities valueForKey:mappedSubentity]; + // NSString *mappedSubentity = [singleRelatedObjectData valueForKey:kMagicalRecordImportRelationshipTypeKey]; + // [subentities valueForKey:mappedSubentity]; } + + return destinationEntity; +} +- (NSManagedObject *) MR_findObjectForRelationship:(NSRelationshipDescription *)relationshipInfo withData:(id)singleRelatedObjectData +{ + NSEntityDescription *destinationEntity = [self MR_targetEntityDescriptionForRelationship:relationshipInfo]; if (destinationEntity == nil) { ARLog(@"Unable to find entity for type '%@'", [singleRelatedObjectData valueForKey:kMagicalRecordImportRelationshipTypeKey]); @@ -97,9 +117,14 @@ NSString * const kMagicalRecordImportRelationshipTypeKey = @"type"; Class managedObjectClass = NSClassFromString([destinationEntity managedObjectClassName]); NSAssert([managedObjectClass isSubclassOfClass:[NSManagedObject class]], @"Entity is not a managed object! Whoa!"); -// NSString *lookupKey = [[destinationEntity userInfo] valueForKey:kNSManagedObjectAttributeJSONKeyMapKey] ?: [destinationEntity name]; + + NSString *primaryKeyName = [[relationshipInfo userInfo] valueForKey:kMagicalRecordImportRelationshipPrimaryKey] ?: [NSString stringWithFormat:@"%@ID", [destinationEntity name]]; + NSAttributeDescription *primaryKeyAttribute = [[destinationEntity attributesByName] valueForKey:primaryKeyName]; + NSString *lookupKey = [[primaryKeyAttribute userInfo] valueForKey:kMagicalRecordImportAttributeKeyMapKey]; - id existingObject = nil; //[managedObjectClass findFirstByAttribute:@"" withValue:@"" inContext:[self managedObjectContext]]; + id lookupValue = [singleRelatedObjectData valueForKey:lookupKey]; + + id existingObject = lookupValue ? [managedObjectClass findFirstByAttribute:primaryKeyName withValue:lookupValue inContext:[self managedObjectContext]] : nil; return existingObject ?: [self MR_createInstanceForEntity:destinationEntity withDictionary:singleRelatedObjectData]; } diff --git a/Unit Tests/Fixtures/SingleRelatedEntity.json b/Unit Tests/Fixtures/SingleRelatedEntity.json index aa1b236..f3bd5a1 100644 --- a/Unit Tests/Fixtures/SingleRelatedEntity.json +++ b/Unit Tests/Fixtures/SingleRelatedEntity.json @@ -44,6 +44,7 @@ , "TestJsonEntityName": { - "sampleAttribute": "Import as sampleAttributeValue" + "sampleAttribute": "Import as sampleAttributeValue", + "id": 42 } } \ No newline at end of file diff --git a/Unit Tests/Fixtures/iOS/TestEntities/_MappedEntity.h b/Unit Tests/Fixtures/iOS/TestEntities/_MappedEntity.h index eaba80f..b62e64a 100644 --- a/Unit Tests/Fixtures/iOS/TestEntities/_MappedEntity.h +++ b/Unit Tests/Fixtures/iOS/TestEntities/_MappedEntity.h @@ -7,6 +7,7 @@ + @interface MappedEntityID : NSManagedObjectID {} @end @@ -27,6 +28,18 @@ +@property (nonatomic, retain) NSNumber *testMappedEntityID; + + +@property long long testMappedEntityIDValue; +- (long long)testMappedEntityIDValue; +- (void)setTestMappedEntityIDValue:(long long)value_; + +//- (BOOL)validateTestMappedEntityID:(id*)value_ error:(NSError**)error_; + + + + @end @@ -43,4 +56,13 @@ +- (NSNumber*)primitiveTestMappedEntityID; +- (void)setPrimitiveTestMappedEntityID:(NSNumber*)value; + +- (long long)primitiveTestMappedEntityIDValue; +- (void)setPrimitiveTestMappedEntityIDValue:(long long)value_; + + + + @end diff --git a/Unit Tests/Fixtures/iOS/TestEntities/_MappedEntity.m b/Unit Tests/Fixtures/iOS/TestEntities/_MappedEntity.m index 7ae864c..833d47a 100644 --- a/Unit Tests/Fixtures/iOS/TestEntities/_MappedEntity.m +++ b/Unit Tests/Fixtures/iOS/TestEntities/_MappedEntity.m @@ -29,6 +29,10 @@ + (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key]; + if ([key isEqualToString:@"testMappedEntityIDValue"]) { + NSSet *affectingKey = [NSSet setWithObject:@"testMappedEntityID"]; + keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKey]; + } return keyPaths; } @@ -43,6 +47,32 @@ +@dynamic testMappedEntityID; + + + +- (long long)testMappedEntityIDValue { + NSNumber *result = [self testMappedEntityID]; + return [result longLongValue]; +} + +- (void)setTestMappedEntityIDValue:(long long)value_ { + [self setTestMappedEntityID:[NSNumber numberWithLongLong:value_]]; +} + +- (long long)primitiveTestMappedEntityIDValue { + NSNumber *result = [self primitiveTestMappedEntityID]; + return [result longLongValue]; +} + +- (void)setPrimitiveTestMappedEntityIDValue:(long long)value_ { + [self setPrimitiveTestMappedEntityID:[NSNumber numberWithLongLong:value_]]; +} + + + + + diff --git a/Unit Tests/Fixtures/iOS/TestModel.xcdatamodeld/TestModel.xcdatamodel/contents b/Unit Tests/Fixtures/iOS/TestModel.xcdatamodeld/TestModel.xcdatamodel/contents index b944720..fc03727 100644 --- a/Unit Tests/Fixtures/iOS/TestModel.xcdatamodeld/TestModel.xcdatamodel/contents +++ b/Unit Tests/Fixtures/iOS/TestModel.xcdatamodeld/TestModel.xcdatamodel/contents @@ -9,6 +9,11 @@ + + + + + @@ -39,6 +44,7 @@ + @@ -48,6 +54,6 @@ - + \ No newline at end of file diff --git a/Unit Tests/ImportSingleEntityWithRelatedEntitiesTests.m b/Unit Tests/ImportSingleEntityWithRelatedEntitiesTests.m index 53b4d1d..698138e 100644 --- a/Unit Tests/ImportSingleEntityWithRelatedEntitiesTests.m +++ b/Unit Tests/ImportSingleEntityWithRelatedEntitiesTests.m @@ -20,11 +20,22 @@ @synthesize testEntity; +- (void) setupTestData +{ + MappedEntity *testMappedEntity = [MappedEntity createEntity]; + testMappedEntity.testMappedEntityIDValue = 42; + testMappedEntity.sampleAttribute = @"This attribute created as part of the test case setup"; + + [[NSManagedObjectContext defaultContext] save]; +} + - (void) setUpClass { [NSManagedObjectModel setDefaultManagedObjectModel:[NSManagedObjectModel managedObjectModelNamed:@"TestModel.momd"]]; [MagicalRecordHelpers setupCoreDataStackWithInMemoryStore]; + [self setupTestData]; + id singleEntity = [FixtureHelpers dataFromJSONFixtureNamed:@"SingleRelatedEntity"]; self.testEntity = [SingleRelatedEntity MR_importFromDictionary:singleEntity]; @@ -93,10 +104,24 @@ //verify mapping in relationship description userinfo NSEntityDescription *mappedEntity = [testEntity entity]; NSRelationshipDescription *testRelationship = [[mappedEntity propertiesByName] valueForKey:@"testMappedRelationship"]; - assertThat([[testRelationship userInfo] valueForKey:@"jsonKeyName"], is(equalTo(@"TestJsonEntityName"))); + assertThat([[testRelationship userInfo] valueForKey:kMagicalRecordImportRelationshipMapKey], is(equalTo(@"TestJsonEntityName"))); assertThat(testRelatedEntity, is(notNilValue())); assertThat([testRelatedEntity sampleAttribute], is(containsString(@"sampleAttributeValue"))); } +- (void) testImportMappedEntityUsingPrimaryRelationshipKey +{ + id testRelatedEntity = testEntity.testMappedRelationship; + + //verify mapping in relationship description userinfo + NSEntityDescription *mappedEntity = [testEntity entity]; + NSRelationshipDescription *testRelationship = [[mappedEntity propertiesByName] valueForKey:@"testMappedRelationship"]; + assertThat([[testRelationship userInfo] valueForKey:kMagicalRecordImportRelationshipPrimaryKey], is(equalTo(@"testMappedEntityID"))); + + // assertThat(testRelatedEntity, is(equalTo(testMappedEntity))); + assertThat([testRelatedEntity testMappedEntityID], is(equalToInteger(42))); + assertThat([testRelatedEntity sampleAttribute], containsString(@"test case setup")); +} + @end