mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-02 17:57:22 +08:00
Added Object Mapping block helpers to RKObjectManager and RKObjectMapping. These enable you to perform ad-hoc object mapping very easily. Extended RKObjectRouter to match on superclasses if no specific route is found. This is helpful when using mocked objects with frameworks like Kiwi. fixes #238
This commit is contained in:
@@ -211,6 +211,63 @@ typedef enum {
|
||||
*/
|
||||
- (RKObjectLoader*)deleteObject:(id<NSObject>)object delegate:(id<RKObjectLoaderDelegate>)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<NSObject>)object method:(RKRequestMethod)method delegate:(id<RKObjectLoaderDelegate>)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<NSObject>)object delegate:(id<RKObjectLoaderDelegate>)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<NSObject>)object delegate:(id<RKObjectLoaderDelegate>)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<NSObject>)object delegate:(id<RKObjectLoaderDelegate>)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<NSObject>)object delegate:(id<RKObjectLoaderDelegate>)delegate block:(void(^)(RKObjectLoader*))block;
|
||||
|
||||
#endif
|
||||
|
||||
//////
|
||||
|
||||
/**
|
||||
|
||||
@@ -190,6 +190,31 @@ static RKObjectManager* sharedManager = nil;
|
||||
return loader;
|
||||
}
|
||||
|
||||
#pragma mark - Block Configured Object Loaders
|
||||
|
||||
- (RKObjectLoader*)sendObject:(id<NSObject>)object method:(RKRequestMethod)method delegate:(id<RKObjectLoaderDelegate>)delegate block:(void(^)(RKObjectLoader*))block {
|
||||
RKObjectLoader* loader = [self objectLoaderForObject:object method:method delegate:delegate];
|
||||
block(loader);
|
||||
[loader send];
|
||||
return loader;
|
||||
}
|
||||
|
||||
- (RKObjectLoader*)getObject:(id<NSObject>)object delegate:(id<RKObjectLoaderDelegate>)delegate block:(void(^)(RKObjectLoader*))block {
|
||||
return [self sendObject:object method:RKRequestMethodGET delegate:delegate block:block];
|
||||
}
|
||||
|
||||
- (RKObjectLoader*)postObject:(id<NSObject>)object delegate:(id<RKObjectLoaderDelegate>)delegate block:(void(^)(RKObjectLoader*))block {
|
||||
return [self sendObject:object method:RKRequestMethodPOST delegate:delegate block:block];
|
||||
}
|
||||
|
||||
- (RKObjectLoader*)putObject:(id<NSObject>)object delegate:(id<RKObjectLoaderDelegate>)delegate block:(void(^)(RKObjectLoader*))block {
|
||||
return [self sendObject:object method:RKRequestMethodPUT delegate:delegate block:block];
|
||||
}
|
||||
|
||||
- (RKObjectLoader*)deleteObject:(id<NSObject>)object delegate:(id<RKObjectLoaderDelegate>)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<NSObject>)object mapResponseWith:(RKObjectMapping*)objectMapping delegate:(id<RKObjectLoaderDelegate>)delegate {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -28,6 +28,23 @@ NSString* const RKObjectMappingNestingAttributeKeyName = @"<RK_NESTING_ATTRIBUTE
|
||||
return [mapping autorelease];
|
||||
}
|
||||
|
||||
+ (id)serializationMapping {
|
||||
return [self mappingForClass:[NSMutableDictionary class]];
|
||||
}
|
||||
|
||||
+ (id)mappingForClass:(Class)objectClass block:(void(^)(RKObjectMapping*))block {
|
||||
RKObjectMapping* mapping = [self mappingForClass:objectClass];
|
||||
block(mapping);
|
||||
return mapping;
|
||||
}
|
||||
|
||||
+ (id)serializationMappingWithBlock:(void(^)(RKObjectMapping*))block {
|
||||
RKObjectMapping* mapping = [self serializationMapping];
|
||||
block(mapping);
|
||||
return mapping;
|
||||
}
|
||||
|
||||
|
||||
- (id)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
|
||||
@@ -27,12 +27,12 @@
|
||||
|
||||
- (void)routeClass:(Class)class toResourcePath:(NSString*)resourcePath forMethodName:(NSString*)methodName {
|
||||
NSString* className = NSStringFromClass(class);
|
||||
if (nil == [_routes objectForKey:className]) {
|
||||
if (nil == [_routes objectForKey:class]) {
|
||||
NSMutableDictionary* dictionary = [NSMutableDictionary dictionary];
|
||||
[_routes setObject:dictionary forKey:className];
|
||||
[_routes setObject:dictionary forKey:class];
|
||||
}
|
||||
|
||||
NSMutableDictionary* classRoutes = [_routes objectForKey:className];
|
||||
NSMutableDictionary* classRoutes = [_routes objectForKey:class];
|
||||
if ([classRoutes objectForKey:methodName]) {
|
||||
[NSException raise:nil format:@"A route has already been registered for class '%@' and HTTP method '%@'", className, methodName];
|
||||
}
|
||||
@@ -75,8 +75,26 @@
|
||||
|
||||
- (NSString*)resourcePathForObject:(NSObject*)object method:(RKRequestMethod)method {
|
||||
NSString* methodName = [self HTTPVerbForMethod:method];
|
||||
NSString* className = NSStringFromClass([object class]);
|
||||
NSDictionary* classRoutes = [_routes objectForKey:className];
|
||||
NSString* className = NSStringFromClass([object class]);
|
||||
NSDictionary* classRoutes = nil;
|
||||
|
||||
// Check for exact matches
|
||||
for (Class possibleClass in _routes) {
|
||||
if ([object isMemberOfClass:possibleClass]) {
|
||||
classRoutes = [_routes objectForKey:possibleClass];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for superclass matches
|
||||
if (! classRoutes) {
|
||||
for (Class possibleClass in _routes) {
|
||||
if ([object isKindOfClass:possibleClass]) {
|
||||
classRoutes = [_routes objectForKey:possibleClass];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NSString* resourcePath = nil;
|
||||
if ((resourcePath = [classRoutes objectForKey:methodName])) {
|
||||
|
||||
Reference in New Issue
Block a user