diff --git a/Code/ObjectMapping/RKObjectManager.h b/Code/ObjectMapping/RKObjectManager.h index e9d6a4ee..37d4b54f 100644 --- a/Code/ObjectMapping/RKObjectManager.h +++ b/Code/ObjectMapping/RKObjectManager.h @@ -211,6 +211,63 @@ typedef enum { */ - (RKObjectLoader*)deleteObject:(id)object delegate:(id)delegate; +//////////////////////////////////////////////////////// +/// @name Block Configured Object Loaders + +#if NS_BLOCKS_AVAILABLE + +/** + Configure and send an object loader after yielding it to a block for configuration. This allows for very succinct on-the-fly + configuration of the request without obtaining an object reference via objectLoaderForObject: and then sending it yourself. + + For example: + + - (BOOL)changePassword:(NSString*)newPassword error:(NSError**)error { + if ([self validatePassword:newPassword error:error]) { + self.password = newPassword; + [[RKObjectManager sharedManager] sendObject:self method:RKRequestMethodPOST delegate:self block:^(RKObjectLoader* loader) { + loader.serializationMIMEType = RKMIMETypeJSON; // We want to send this request as JSON + loader.targetObject = nil; // Map the results back onto a new object instead of self + // Set up a custom serialization mapping to handle this request + loader.serializationMapping = [RKObjectMapping serializationMappingWithBlock:^(RKObjectMapping* mapping) { + [mapping mapAttributes:@"password", nil]; + }]; + }]; + } + } + */ +- (RKObjectLoader*)sendObject:(id)object method:(RKRequestMethod)method delegate:(id)delegate block:(void(^)(RKObjectLoader*))block; + +/** + GET a remote object instance and yield the object loader to the block before sending + + @see sendObject:method:delegate:block + */ +- (RKObjectLoader*)getObject:(id)object delegate:(id)delegate block:(void(^)(RKObjectLoader*))block; + +/** + POST a remote object instance and yield the object loader to the block before sending + + @see sendObject:method:delegate:block + */ +- (RKObjectLoader*)postObject:(id)object delegate:(id)delegate block:(void(^)(RKObjectLoader*))block; + +/** + PUT a remote object instance and yield the object loader to the block before sending + + @see sendObject:method:delegate:block + */ +- (RKObjectLoader*)putObject:(id)object delegate:(id)delegate block:(void(^)(RKObjectLoader*))block; + +/** + DELETE a remote object instance and yield the object loader to the block before sending + + @see sendObject:method:delegate:block + */ +- (RKObjectLoader*)deleteObject:(id)object delegate:(id)delegate block:(void(^)(RKObjectLoader*))block; + +#endif + ////// /** diff --git a/Code/ObjectMapping/RKObjectManager.m b/Code/ObjectMapping/RKObjectManager.m index b584920d..646bb084 100644 --- a/Code/ObjectMapping/RKObjectManager.m +++ b/Code/ObjectMapping/RKObjectManager.m @@ -190,6 +190,31 @@ static RKObjectManager* sharedManager = nil; return loader; } +#pragma mark - Block Configured Object Loaders + +- (RKObjectLoader*)sendObject:(id)object method:(RKRequestMethod)method delegate:(id)delegate block:(void(^)(RKObjectLoader*))block { + RKObjectLoader* loader = [self objectLoaderForObject:object method:method delegate:delegate]; + block(loader); + [loader send]; + return loader; +} + +- (RKObjectLoader*)getObject:(id)object delegate:(id)delegate block:(void(^)(RKObjectLoader*))block { + return [self sendObject:object method:RKRequestMethodGET delegate:delegate block:block]; +} + +- (RKObjectLoader*)postObject:(id)object delegate:(id)delegate block:(void(^)(RKObjectLoader*))block { + return [self sendObject:object method:RKRequestMethodPOST delegate:delegate block:block]; +} + +- (RKObjectLoader*)putObject:(id)object delegate:(id)delegate block:(void(^)(RKObjectLoader*))block { + return [self sendObject:object method:RKRequestMethodPUT delegate:delegate block:block]; +} + +- (RKObjectLoader*)deleteObject:(id)object delegate:(id)delegate block:(void(^)(RKObjectLoader*))block { + return [self sendObject:object method:RKRequestMethodDELETE delegate:delegate block:block]; +} + #pragma mark - Object Instance Loaders for Non-nested JSON - (RKObjectLoader*)getObject:(id)object mapResponseWith:(RKObjectMapping*)objectMapping delegate:(id)delegate { diff --git a/Code/ObjectMapping/RKObjectMapping.h b/Code/ObjectMapping/RKObjectMapping.h index cdedd625..8b261a49 100644 --- a/Code/ObjectMapping/RKObjectMapping.h +++ b/Code/ObjectMapping/RKObjectMapping.h @@ -123,6 +123,53 @@ relationship. Relationships are processed using an object mapping as well. */ + (id)mappingForClass:(Class)objectClass; +/** + Returns an object mapping useful for configuring a serialization mapping. The object + class is configured as NSMutableDictionary + */ ++ (id)serializationMapping; + +#if NS_BLOCKS_AVAILABLE +/** + Returns an object mapping targeting the specified class. The RKObjectMapping instance will + be yieled to the block so that you can perform on the fly configuration without having to + obtain a reference variable for the mapping. + + For example, consider we have a one-off request that will load a few attributes for our object. + Using blocks, this is very succinct: + + [[RKObjectManager sharedManager] postObject:self delegate:self block:^(RKObjectLoader* loader) { + loader.objectMapping = [RKObjectMapping mappingForClass:[Person class] block:^(RKObjectMapping* mapping) { + [mapping mapAttributes:@"email", @"first_name", nil]; + }]; + }]; + */ ++ (id)mappingForClass:(Class)objectClass block:(void(^)(RKObjectMapping*))block; + +/** + Returns serialization mapping for encoding a local object to a dictionary for transport. The RKObjectMapping instance will + be yieled to the block so that you can perform on the fly configuration without having to + obtain a reference variable for the mapping. + + For example, consider we have a one-off request within which we want to post a subset of our object + data. Using blocks, this is very succinct: + + - (BOOL)changePassword:(NSString*)newPassword error:(NSError**)error { + if ([self validatePassword:newPassword error:error]) { + self.password = newPassword; + [[RKObjectManager sharedManager] putObject:self delegate:self block:^(RKObjectLoader* loader) { + loader.serializationMapping = [RKObjectMapping serializationMappingWithBlock:^(RKObjectMapping* mapping) { + [mapping mapAttributes:@"password", nil]; + }]; + }]; + } + } + + Using the block forms we are able to quickly configure and send this request on the fly. + */ ++ (id)serializationMappingWithBlock:(void(^)(RKObjectMapping*))block; +#endif + /** Add a configured attribute mapping to this object mapping diff --git a/Code/ObjectMapping/RKObjectMapping.m b/Code/ObjectMapping/RKObjectMapping.m index 58930c81..04fd5446 100644 --- a/Code/ObjectMapping/RKObjectMapping.m +++ b/Code/ObjectMapping/RKObjectMapping.m @@ -28,6 +28,23 @@ NSString* const RKObjectMappingNestingAttributeKeyName = @"