mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-01-12 22:51:50 +08:00
Relax the use of use an the informal procotol for the errorMessage property in favor of the description method. closes #1104, closes #1087, closes #1095
* Change contract to the use the `description` method instead of `errorMessage`. This makes it work with any class out of the box * Add import for RKErrorMessage to the Support.h header so it is immediately available * Fix incorrect keyPath in the README.md * Add additional notes about how the errors are constructed to the README
This commit is contained in:
@@ -197,9 +197,9 @@
|
||||
/**
|
||||
Returns a representation of a mapping result as an `NSError` value.
|
||||
|
||||
The returned `NSError` object is in the `RKErrorDomain` domain and has the `RKMappingErrorFromMappingResult` code. The value for the `NSLocalizedDescriptionKey` is computed by retrieving the objects in the mapping result as an array, evaluating `valueForKeyPath:@"errorMessage"` against the array, and joining the returned error messages by comma to form a single string value. The source error objects are returned with the `NSError` in the `userInfo` dictionary under the `RKObjectMapperErrorObjectsKey` key.
|
||||
The returned `NSError` object is in the `RKErrorDomain` domain and has the `RKMappingErrorFromMappingResult` code. The value for the `NSLocalizedDescriptionKey` is computed by retrieving the objects in the mapping result as an array, evaluating `valueForKeyPath:@"description"` against the array, and joining the returned error messages by comma to form a single string value. The source error objects are returned with the `NSError` in the `userInfo` dictionary under the `RKObjectMapperErrorObjectsKey` key.
|
||||
|
||||
The `errorMessage` property is significant as it is an informal protocol that must be adopted by objects wishing to representing response errors.
|
||||
This implementation assumes that the class used to represent the response error will return a string description of the client side error when sent the `description` message.
|
||||
|
||||
@return An error object representing the objects contained in the mapping result.
|
||||
@see `RKErrorMessage`
|
||||
|
||||
@@ -37,7 +37,7 @@ NSError *RKErrorFromMappingResult(RKMappingResult *mappingResult)
|
||||
NSArray *collection = [mappingResult array];
|
||||
NSString *description = nil;
|
||||
if ([collection count] > 0) {
|
||||
description = [[collection valueForKeyPath:@"errorMessage"] componentsJoinedByString:@", "];
|
||||
description = [[collection valueForKeyPath:@"description"] componentsJoinedByString:@", "];
|
||||
} else {
|
||||
RKLogWarning(@"Expected mapping result to contain at least one object to construct an error");
|
||||
}
|
||||
|
||||
@@ -23,10 +23,6 @@
|
||||
/**
|
||||
The `RKErrorMessage` is a simple class used for representing error messages returned by a remote backend system with which the client application is communicating. Error messages are typically returned in a response body in the Client Error class (status code 4xx range).
|
||||
|
||||
## Error Message Informal Protocol
|
||||
|
||||
The `errorMessage` property method is the sole method of an informal protocol that must be adopted by objects wishing to represent error messages within RestKit. This protocol is by the `RKErrorFromMappingResult` function when constructing `NSError` messages from a mapped response body.
|
||||
|
||||
@see `RKErrorFromMappingResult`
|
||||
*/
|
||||
@interface RKErrorMessage : NSObject
|
||||
|
||||
@@ -24,8 +24,7 @@
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"<%@:%p error message = \"%@\" userInfo = %@>",
|
||||
NSStringFromClass([self class]), self, self.errorMessage, self.userInfo];
|
||||
return self.errorMessage;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
// Load shared support code
|
||||
#import "RKErrors.h"
|
||||
#import "RKErrorMessage.h"
|
||||
#import "RKMIMETypes.h"
|
||||
#import "RKLog.h"
|
||||
#import "RKPathMatcher.h"
|
||||
|
||||
@@ -230,9 +230,10 @@ operation.managedObjectCache = managedObjectStore.managedObjectCache;
|
||||
// GET /articles/error.json returns a 422 (Unprocessable Entity)
|
||||
// JSON looks like {"errors": "Some Error Has Occurred"}
|
||||
|
||||
// You can map errors to any class, but `RKErrorMessage` is included for free
|
||||
RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
|
||||
// The entire value at the source key path containing the errors maps to the message
|
||||
[errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:[NSNull null] toKeyPath:@"message"]];
|
||||
[errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:[NSNull null] toKeyPath:@"errorMessage"]];
|
||||
|
||||
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassClientError);
|
||||
// Any response in the 4xx status code range with an "errors" key path uses this mapping
|
||||
@@ -241,6 +242,7 @@ RKResponseDescriptor *errorDescriptor = [RKResponseDescriptor responseDescriptor
|
||||
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://restkit.org/articles/error.json"]];
|
||||
RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[errorDescriptor]];
|
||||
[operation setCompletionBlockWithSuccess:nil failure:^(RKObjectRequestOperation *operation, NSError *error) {
|
||||
// The `description` method of the class the error is mapped to is used to construct the value of the localizedDescription
|
||||
NSLog(@"Loaded this error: %@", [error localizedDescription]);
|
||||
}];
|
||||
```
|
||||
|
||||
@@ -14,6 +14,20 @@
|
||||
|
||||
NSString *RKPathAndQueryStringFromURLRelativeToURL(NSURL *URL, NSURL *baseURL);
|
||||
|
||||
@interface RKServerError : NSObject
|
||||
@property (nonatomic, copy) NSString *message;
|
||||
@property (nonatomic, assign) NSInteger code;
|
||||
@end
|
||||
|
||||
@implementation RKServerError
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"%@ (%ld)", self.message, (long) self.code];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface RKObjectResponseMapperOperationTest : RKTestCase
|
||||
|
||||
@end
|
||||
@@ -121,6 +135,21 @@ NSString *RKPathAndQueryStringFromURLRelativeToURL(NSURL *URL, NSURL *baseURL);
|
||||
expect([mapper.error localizedDescription]).to.equal(@"Loaded an unprocessable client error response (422)");
|
||||
}
|
||||
|
||||
- (void)testMappingServerErrorToCustomErrorClass
|
||||
{
|
||||
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKServerError class]];
|
||||
[mapping addAttributeMappingsFromArray:@[ @"code", @"message" ]];
|
||||
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:nil keyPath:nil statusCodes:[NSIndexSet indexSetWithIndex:422]];
|
||||
NSURL *URL = [NSURL URLWithString:@"http://restkit.org"];
|
||||
NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:URL statusCode:422 HTTPVersion:@"1.1" headerFields:@{@"Content-Type": @"application/json"}];
|
||||
NSData *data = [@"{\"code\": 12345, \"message\": \"This is the error message\"}" dataUsingEncoding:NSUTF8StringEncoding];
|
||||
RKObjectResponseMapperOperation *mapper = [[RKObjectResponseMapperOperation alloc] initWithResponse:response data:data responseDescriptors:@[responseDescriptor]];
|
||||
[mapper start];
|
||||
expect(mapper.error).notTo.beNil();
|
||||
expect(mapper.error.code).to.equal(RKMappingErrorFromMappingResult);
|
||||
expect([mapper.error localizedDescription]).to.equal(@"This is the error message (12345)");
|
||||
}
|
||||
|
||||
#pragma mark - Response Descriptor Matching
|
||||
|
||||
- (void)testThatResponseMapperMatchesBaseURLWithoutPathAppropriately
|
||||
|
||||
Reference in New Issue
Block a user