Skip to content

Commit

Permalink
Add identificationPredicateBlock to filter matches based on the JSON …
Browse files Browse the repository at this point in the history
…representation
  • Loading branch information
Simon Booth committed May 1, 2015
1 parent 53ba779 commit 8d08948
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 0 deletions.
7 changes: 7 additions & 0 deletions Code/CoreData/RKEntityMapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@
*/
@property (nonatomic, copy) NSPredicate *identificationPredicate;

/**
An optional block which returns a predicate used to filter identified objects during mapping.
@return The identification predicate block.
*/
@property (nonatomic, copy) NSPredicate *(^identificationPredicateBlock)(NSDictionary *representation, NSManagedObjectContext *managedObjectContext);

/**
An optional attribute of the receiver's entity that can be used to detect modification of a given instance. This is used to improve the performance of mapping operations by skipping the property mappings for a given object if it is found to be not modified.
Expand Down
1 change: 1 addition & 0 deletions Code/CoreData/RKEntityMapping.m
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ - (id)copyWithZone:(NSZone *)zone
copy.entity = self.entity;
copy.identificationAttributes = self.identificationAttributes;
copy.identificationPredicate = self.identificationPredicate;
copy.identificationPredicateBlock = self.identificationPredicateBlock;
copy.deletionPredicate = self.deletionPredicate;
copy.modificationAttribute = self.modificationAttribute;
copy.mutableConnections = [NSMutableArray array];
Expand Down
4 changes: 4 additions & 0 deletions Code/CoreData/RKManagedObjectMappingOperationDataSource.m
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,10 @@ - (id)mappingOperation:(RKMappingOperation *)mappingOperation targetObjectForRep
attributeValues:entityIdentifierAttributes
inManagedObjectContext:self.managedObjectContext];
if (entityMapping.identificationPredicate) objects = [objects filteredSetUsingPredicate:entityMapping.identificationPredicate];
if (entityMapping.identificationPredicateBlock) {
NSPredicate *predicate = entityMapping.identificationPredicateBlock(representation, self.managedObjectContext);
if (predicate) objects = [objects filteredSetUsingPredicate:predicate];
}
if ([objects count] > 0) {
managedObject = [objects anyObject];
if ([objects count] > 1) RKLogWarning(@"Managed object cache returned %ld objects for the identifier configured for the '%@' entity, expected 1.", (long) [objects count], [entity name]);
Expand Down
2 changes: 2 additions & 0 deletions Tests/Logic/CoreData/RKEntityMappingTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ - (void)testEntityMappingCopy
RKEntityMapping *entityMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
entityMapping.identificationAttributes = RKIdentificationAttributesInferredFromEntity(entityMapping.entity);
entityMapping.identificationPredicate = [NSPredicate predicateWithValue:YES];
entityMapping.identificationPredicateBlock = ^(NSDictionary *representation, NSManagedObjectContext *context) { return [NSPredicate predicateWithValue:YES]; };
entityMapping.deletionPredicate = [NSPredicate predicateWithValue:NO];
[entityMapping setModificationAttributeForName:@"railsID"];
[entityMapping addConnectionForRelationship:@"cats" connectedBy:@{ @"railsID": @"railsID", @"name": @"name" }];
Expand All @@ -337,6 +338,7 @@ - (void)testEntityMappingCopy
expect(entityMappingCopy.entity).to.equal(entityMapping.entity);
expect(entityMappingCopy.identificationAttributes).to.equal(entityMapping.identificationAttributes);
expect(entityMappingCopy.identificationPredicate).to.equal(entityMapping.identificationPredicate);
expect(entityMappingCopy.identificationPredicateBlock).to.equal(entityMapping.identificationPredicateBlock);
expect(entityMappingCopy.deletionPredicate).to.equal(entityMapping.deletionPredicate);
expect(entityMappingCopy.modificationAttribute).to.equal(entityMapping.modificationAttribute);
expect(entityMappingCopy.connections.count == entityMapping.connections.count);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,42 @@ - (void)testEntityIdentifierWithPredicate
expect(object).to.equal(human1);
}

- (void)testEntityIdentifierWithPredicateBlock
{
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
managedObjectStore.managedObjectCache = [RKFetchRequestManagedObjectCache new];
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
mapping.identificationAttributes = @[ @"railsID" ];
mapping.identificationPredicateBlock = ^(NSDictionary *representation, NSManagedObjectContext *context) {
return [NSPredicate predicateWithFormat:@"age + 94 < %@", representation[@"id"]];
};
[mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"id" toKeyPath:@"railsID"]];

// Create two humans matching the identifier, but differ in matching the
RKHuman *human1 = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
human1.name = @"Colin";
human1.railsID = @123;
human1.age = @28;

RKHuman *human2 = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
human2.name = @"Blake";
human2.railsID = @123;
human2.age = @30;
[managedObjectStore.persistentStoreManagedObjectContext save:nil];

NSError *error = nil;
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Human"];
NSUInteger count = [managedObjectStore.persistentStoreManagedObjectContext countForFetchRequest:fetchRequest error:&error];
expect(count).to.beGreaterThan(0);

RKManagedObjectMappingOperationDataSource *dataSource = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext
cache:managedObjectStore.managedObjectCache];
NSDictionary *data = @{@"id": @123};
id object = [dataSource mappingOperation:nil targetObjectForRepresentation:data withMapping:mapping inRelationship:nil];
expect(object).notTo.beNil();
expect(object).to.equal(human1);
}

- (void)testMappingInPrivateQueue
{
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
Expand Down

0 comments on commit 8d08948

Please sign in to comment.