Eliminate methods wrapping functionality provided by RKConnectionMapping within RKEntityMapping for simplicity and clarity

This commit is contained in:
Blake Watters
2012-08-28 13:37:07 -04:00
parent 00a89d3a4b
commit 15acf30a66
3 changed files with 75 additions and 184 deletions

View File

@@ -102,6 +102,7 @@
@param connectionMapping The connection mapping to be added.
*/
- (void)addConnectionMapping:(RKConnectionMapping *)connectionMapping;
- (void)addConnectionMappingsFromArray:(NSArray *)arrayOfConnectionMappings;
/**
Removes a connection mapping from the receiver.
@@ -110,73 +111,6 @@
*/
- (void)removeConnectionMapping:(RKConnectionMapping *)connectionMapping;
/**
Instructs RestKit to connect a relationship of the object being mapped to the
appropriate target object(s). It does this by using the value of the object's
fromKeyPath attribute to query instances of the target entity that have the
same value in their toKeyPath attribute.
Note that connectRelationship runs *after* an object's attributes have been
mapped and is dependent upon the results of those mappings. Also, connectRelationship
will never create a new object - it simply looks up existing objects. In effect,
connectRelationship allows foreign key relationships between managed objects
to be automatically maintained from the server to the underlying Core Data object graph.
For example, given a Project object associated with a User, where the 'user' relationship is
specified by a userID property on the managed object:
[mapping connectRelationship:@"user" withMapping:userMapping fromKeyPath:@"userId" toKeyPath:@"id"];
Will hydrate the 'user' association on the managed object with the object
in the local object graph having the primary key specified in the managed object's
userID property.
You can also do the reverse. Given a User object associated with a Project, with a
'project' relationship:
[mapping connectRelationship:@"project" fromKeyPath:@"id" toKeyPath:@"userId" withMapping:projectMapping];
*/
- (void)connectRelationship:(NSString *)relationshipName fromKeyPath:(NSString *)sourceKeyPath toKeyPath:(NSString *)destinationKeyPath withMapping:(RKMapping *)objectOrDynamicMapping;
/**
Conditionally connect a relationship of the object being mapped when the object being mapped has
keyPath equal to a specified value.
For example, given a Project object associated with a User, where the 'admin' relationship is
specified by a adminID property on the managed object:
[mapping connectRelationship:@"admin" fromKeyPath:@"adminId" toKeyPath:@"id" withMapping:userMapping whenValueOfKeyPath:@"userType" isEqualTo:@"Admin"];
Will hydrate the 'admin' association on the managed object with the object
in the local object graph having the primary key specified in the managed object's
userID property. Note that this connection will only occur when the Product's 'userType'
property equals 'Admin'. In cases where no match occurs, the relationship connection is skipped.
@see connectRelationship:withObjectForPrimaryKeyAttribute:
*/
- (void)connectRelationship:(NSString *)relationshipName fromKeyPath:(NSString *)sourceKeyPath toKeyPath:(NSString *)destinationKeyPath withMapping:(RKMapping *)objectOrDynamicMapping whenValueOfKeyPath:(NSString *)keyPath isEqualTo:(id)value;
/**
Conditionally connect a relationship of the object being mapped when the object being mapped has
block evaluate to YES. This variant is useful in cases where you want to execute an arbitrary
block to determine whether or not to connect a relationship.
For example, given a Project object associated with a User, where the 'admin' relationship is
specified by a adminID property on the managed object:
[mapping connectRelationship:@"admin" fromKeyPath:@"adminId" toKeyPath:@"adminID" withMapping:userMapping usingEvaluationBlock:^(id data) {
return [User isAuthenticated];
}];
Will hydrate the 'admin' association on the managed object with the object
in the local object graph having the primary key specified in the managed object's
userID property. Note that this connection will only occur when the provided block evalutes to YES.
In cases where no match occurs, the relationship connection is skipped.
@see connectRelationship:withObjectForPrimaryKeyAttribute:
*/
- (void)connectRelationship:(NSString *)relationshipName fromKeyPath:(NSString *)sourceKeyPath toKeyPath:(NSString *)destinationKeyPath withMapping:(RKMapping *)objectOrDynamicMapping usingEvaluationBlock:(BOOL (^)(id data))block;
/**
Returns the default value for the specified attribute as expressed in the Core Data entity definition. This value will
be assigned if the object mapping is applied and a value for a missing attribute is not present in the payload.
@@ -184,19 +118,3 @@
- (id)defaultValueForMissingAttribute:(NSString *)attributeName;
@end
@interface RKEntityMapping (Deprecations)
/* Deprecated Initialization API's */
+ (id)mappingForClass:(Class)objectClass inManagedObjectStore:(RKManagedObjectStore *)objectStore DEPRECATED_ATTRIBUTE_MESSAGE("Use mappingForEntityForName:inManagedObjectStore:");
+ (RKEntityMapping *)mappingForEntity:(NSEntityDescription *)entity inManagedObjectStore:(RKManagedObjectStore *)objectStore DEPRECATED_ATTRIBUTE_MESSAGE("Use mappingForEntityForName:inManagedObjectStore:");
+ (RKEntityMapping *)mappingForEntityWithName:(NSString *)entityName inManagedObjectStore:(RKManagedObjectStore *)objectStore DEPRECATED_ATTRIBUTE_MESSAGE("Use mappingForEntityForName:inManagedObjectStore:");
- (id)initWithEntity:(NSEntityDescription *)entity inManagedObjectStore:(RKManagedObjectStore *)objectStore DEPRECATED_ATTRIBUTE_MESSAGE("Use mappingForEntity:");
/* Deprecated Connection API's */
- (void)connectRelationship:(NSString *)relationshipName withObjectForPrimaryKeyAttribute:(NSString *)primaryKeyAttribute DEPRECATED_ATTRIBUTE_MESSAGE("Use connectRelationship:withMapping:fromKeyPath:toKeyPath:");
- (void)connectRelationship:(NSString *)relationshipName withObjectForPrimaryKeyAttribute:(NSString *)primaryKeyAttribute whenValueOfKeyPath:(NSString *)keyPath isEqualTo:(id)value DEPRECATED_ATTRIBUTE_MESSAGE("Use connectRelationship:withMapping:fromKeyPath:toKeyPath:whenValueOfKeyPath:isEqualTo:");
- (void)connectRelationshipsWithObjectsForPrimaryKeyAttributes:(NSString *)firstRelationshipName, ... NS_REQUIRES_NIL_TERMINATION DEPRECATED_ATTRIBUTE_MESSAGE("Use connectRelationship:withMapping:fromKeyPath:toKeyPath:");
- (void)connectRelationship:(NSString *)relationshipName withObjectForPrimaryKeyAttribute:(NSString *)primaryKeyAttribute usingEvaluationBlock:(BOOL (^)(id data))block DEPRECATED_ATTRIBUTE_MESSAGE("Use connectRelationship:withMapping:fromKeyPath:toKeyPath:usingEvaluationBlock:");
@end

View File

@@ -24,6 +24,7 @@
#import "RKPropertyInspector+CoreData.h"
#import "NSEntityDescription+RKAdditions.h"
#import "RKLog.h"
#import "RKRelationshipMapping.h"
// Set Logging Component
#undef RKLogComponent
@@ -33,6 +34,7 @@
BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue);
@interface RKEntityMapping ()
@property (nonatomic, assign, readwrite) Class objectClass;
@property (nonatomic, retain, readwrite) NSEntityDescription *entity;
@property (nonatomic, retain) NSMutableArray *mutableConnections;
@end
@@ -108,19 +110,6 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue);
return nil;
}
- (RKMapping *)objectMappingForRelationship:(NSString *)relationshipName
{
RKRelationshipMapping *relationshipMapping = [self mappingForRelationship:relationshipName];
return relationshipMapping.mapping;
}
- (NSString *)primaryKeyPathForRelationship:(NSString *)relationshipName
{
RKMapping* mappingDef = [self objectMappingForRelationship:relationshipName];
RKEntityMapping *objectMapping = (RKEntityMapping *) mappingDef;
return [objectMapping primaryKeyAttribute];
}
- (void)addConnectionMapping:(RKConnectionMapping *)mapping
{
RKConnectionMapping *connectionMapping = [self connectionMappingForRelationshipWithName:mapping.relationshipName];
@@ -130,35 +119,18 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue);
[self.mutableConnections addObject:mapping];
}
- (void)addConnectionMappingsFromArray:(NSArray *)arrayOfConnectionMappings
{
for (RKConnectionMapping *connectionMapping in arrayOfConnectionMappings) {
[self addConnectionMapping:connectionMapping];
}
}
- (void)removeConnectionMapping:(RKConnectionMapping *)connectionMapping
{
[self.mutableConnections removeObject:connectionMapping];
}
- (void)connectRelationship:(NSString *)relationshipName fromKeyPath:(NSString *)sourceKeyPath toKeyPath:(NSString *)destinationKeyPath withMapping:(RKMapping *)objectOrDynamicMapping
{
NSAssert(sourceKeyPath, @"Cannot connect relationship: mapping for %@ has no source key attribute specified", relationshipName);
NSAssert(destinationKeyPath, @"Cannot connect relationship: mapping for %@ has no destination key attribute specified", relationshipName);
RKConnectionMapping *mapping = [RKConnectionMapping connectionMappingForRelationship:relationshipName fromKeyPath:sourceKeyPath toKeyPath:destinationKeyPath withMapping:objectOrDynamicMapping];
[self addConnectionMapping:mapping];
}
- (void)connectRelationship:(NSString *)relationshipName fromKeyPath:(NSString *)sourceKeyPath toKeyPath:(NSString *)destinationKeyPath withMapping:(RKMapping *)objectOrDynamicMapping whenValueOfKeyPath:(NSString *)keyPath isEqualTo:(id)value
{
RKDynamicMappingMatcher *matcher = [[RKDynamicMappingMatcher alloc] initWithKey:keyPath value:value primaryKeyAttribute:sourceKeyPath];
RKConnectionMapping *mapping = [RKConnectionMapping connectionMappingForRelationship:relationshipName fromKeyPath:sourceKeyPath toKeyPath:destinationKeyPath withMapping:objectOrDynamicMapping matcher:matcher];
[self addConnectionMapping:mapping];
[matcher release];
}
- (void)connectRelationship:(NSString *)relationshipName fromKeyPath:(NSString *)sourceKeyPath toKeyPath:(NSString *)destinationKeyPath withMapping:(RKMapping *)objectOrDynamicMapping usingEvaluationBlock:(BOOL (^)(id data))block
{
RKDynamicMappingMatcher *matcher = [[RKDynamicMappingMatcher alloc] initWithPrimaryKeyAttribute:sourceKeyPath evaluationBlock:block];
RKConnectionMapping *mapping = [RKConnectionMapping connectionMappingForRelationship:relationshipName fromKeyPath:sourceKeyPath toKeyPath:destinationKeyPath withMapping:objectOrDynamicMapping matcher:matcher];
[self addConnectionMapping:mapping];
[matcher release];
}
- (id)defaultValueForMissingAttribute:(NSString *)attributeName
{
NSAttributeDescription *desc = [[self.entity attributesByName] valueForKey:attributeName];
@@ -197,67 +169,3 @@ BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue);
}
@end
@implementation RKEntityMapping (Deprecations)
+ (id)mappingForClass:(Class)objectClass inManagedObjectStore:(RKManagedObjectStore *)objectStore DEPRECATED_ATTRIBUTE
{
return [self mappingForEntityWithName:NSStringFromClass(objectClass) inManagedObjectStore:objectStore];
}
+ (RKEntityMapping *)mappingForEntity:(NSEntityDescription *)entity inManagedObjectStore:(RKManagedObjectStore *)objectStore DEPRECATED_ATTRIBUTE
{
return [[[self alloc] initWithEntity:entity inManagedObjectStore:objectStore] autorelease];
}
+ (RKEntityMapping *)mappingForEntityWithName:(NSString *)entityName inManagedObjectStore:(RKManagedObjectStore *)objectStore DEPRECATED_ATTRIBUTE
{
return [self mappingForEntity:[NSEntityDescription entityForName:entityName inManagedObjectContext:objectStore.primaryManagedObjectContext]
inManagedObjectStore:objectStore];
}
- (id)initWithEntity:(NSEntityDescription *)entity inManagedObjectStore:(RKManagedObjectStore *)objectStore DEPRECATED_ATTRIBUTE
{
return [self initWithEntity:entity];
}
/* Deprecated */
- (void)connectRelationship:(NSString*)relationshipName withObjectForPrimaryKeyAttribute:(NSString *)primaryKeyAttribute
{
RKMapping *objectOrDynamicMapping = [self objectMappingForRelationship:relationshipName];
NSString *sourceKeyPath = primaryKeyAttribute;
NSString *destinationKeyPath = [self primaryKeyPathForRelationship:relationshipName];
RKConnectionMapping *mapping = [RKConnectionMapping connectionMappingForRelationship:relationshipName fromKeyPath:sourceKeyPath toKeyPath:destinationKeyPath withMapping:objectOrDynamicMapping];
[self addConnectionMapping:mapping];
}
- (void)connectRelationshipsWithObjectsForPrimaryKeyAttributes:(NSString *)firstRelationshipName, ...
{
va_list args;
va_start(args, firstRelationshipName);
for (NSString *relationshipName = firstRelationshipName; relationshipName != nil; relationshipName = va_arg(args, NSString*)) {
NSString *primaryKeyAttribute = va_arg(args, NSString *);
[self connectRelationship:relationshipName withObjectForPrimaryKeyAttribute:primaryKeyAttribute];
// TODO: Raise proper exception here, argument error...
}
va_end(args);
}
- (void)connectRelationship:(NSString *)relationshipName withObjectForPrimaryKeyAttribute:(NSString *)primaryKeyAttribute whenValueOfKeyPath:(NSString*)keyPath isEqualTo:(id)value
{
RKMapping *objectOrDynamicMapping = [self objectMappingForRelationship:relationshipName];
NSString *sourceKeyPath = primaryKeyAttribute;
NSString *destinationKeyPath = [self primaryKeyPathForRelationship:relationshipName];
[self connectRelationship:relationshipName fromKeyPath:sourceKeyPath toKeyPath:destinationKeyPath withMapping:objectOrDynamicMapping whenValueOfKeyPath:keyPath isEqualTo:value];
}
- (void)connectRelationship:(NSString *)relationshipName withObjectForPrimaryKeyAttribute:(NSString *)primaryKeyAttribute usingEvaluationBlock:(BOOL (^)(id data))block
{
RKMapping *objectOrDynamicMapping = [self objectMappingForRelationship:relationshipName];
NSString *sourceKeyPath = primaryKeyAttribute;
NSString *destinationKeyPath = [self primaryKeyPathForRelationship:relationshipName];
[self connectRelationship:relationshipName fromKeyPath:sourceKeyPath toKeyPath:destinationKeyPath withMapping:objectOrDynamicMapping usingEvaluationBlock:block];
}
@end

View File

@@ -28,6 +28,71 @@
typedef id(^RKObjectConnectionBlock)(RKConnectionMapping *mapping, id source);
// Defines the rules for connecting relationsips
/**
Instructs RestKit to connect a relationship of the object being mapped to the
appropriate target object(s). It does this by using the value of the object's
fromKeyPath attribute to query instances of the target entity that have the
same value in their toKeyPath attribute.
Note that connectRelationship runs *after* an object's attributes have been
mapped and is dependent upon the results of those mappings. Also, connectRelationship
will never create a new object - it simply looks up existing objects. In effect,
connectRelationship allows foreign key relationships between managed objects
to be automatically maintained from the server to the underlying Core Data object graph.
For example, given a Project object associated with a User, where the 'user' relationship is
specified by a userID property on the managed object:
[mapping connectRelationship:@"user" withMapping:userMapping fromKeyPath:@"userId" toKeyPath:@"id"];
Will hydrate the 'user' association on the managed object with the object
in the local object graph having the primary key specified in the managed object's
userID property.
You can also do the reverse. Given a User object associated with a Project, with a
'project' relationship:
[mapping connectRelationship:@"project" fromKeyPath:@"id" toKeyPath:@"userId" withMapping:projectMapping];
*/
//- (void)connectRelationship:(NSString *)relationshipName fromKeyPath:(NSString *)sourceKeyPath toKeyPath:(NSString *)destinationKeyPath withMapping:(RKMapping *)objectOrDynamicMapping DEPRECATED_ATTRIBUTE;
/**
Conditionally connect a relationship of the object being mapped when the object being mapped has
keyPath equal to a specified value.
For example, given a Project object associated with a User, where the 'admin' relationship is
specified by a adminID property on the managed object:
[mapping connectRelationship:@"admin" fromKeyPath:@"adminId" toKeyPath:@"id" withMapping:userMapping whenValueOfKeyPath:@"userType" isEqualTo:@"Admin"];
Will hydrate the 'admin' association on the managed object with the object
in the local object graph having the primary key specified in the managed object's
userID property. Note that this connection will only occur when the Product's 'userType'
property equals 'Admin'. In cases where no match occurs, the relationship connection is skipped.
@see connectRelationship:withObjectForPrimaryKeyAttribute:
*/
// - (void)connectRelationship:(NSString *)relationshipName fromKeyPath:(NSString *)sourceKeyPath toKeyPath:(NSString *)destinationKeyPath withMapping:(RKMapping *)objectOrDynamicMapping whenValueOfKeyPath:(NSString *)keyPath isEqualTo:(id)value DEPRECATED_ATTRIBUTE;
/**
Conditionally connect a relationship of the object being mapped when the object being mapped has
block evaluate to YES. This variant is useful in cases where you want to execute an arbitrary
block to determine whether or not to connect a relationship.
For example, given a Project object associated with a User, where the 'admin' relationship is
specified by a adminID property on the managed object:
[mapping connectRelationship:@"admin" fromKeyPath:@"adminId" toKeyPath:@"adminID" withMapping:userMapping usingEvaluationBlock:^(id data) {
return [User isAuthenticated];
}];
Will hydrate the 'admin' association on the managed object with the object
in the local object graph having the primary key specified in the managed object's
userID property. Note that this connection will only occur when the provided block evalutes to YES.
In cases where no match occurs, the relationship connection is skipped.
@see connectRelationship:withObjectForPrimaryKeyAttribute:
*/
@interface RKConnectionMapping : NSObject
@property (nonatomic, retain, readonly) NSString *relationshipName;