mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-01-12 22:51:50 +08:00
Merge branch 'bugfix/inappropriate-objectrequestoperations' into development
This commit is contained in:
@@ -31,6 +31,8 @@
|
||||
#import "RKPathMatcher.h"
|
||||
#import "RKMappingErrors.h"
|
||||
#import "RKPaginator.h"
|
||||
#import "RKDynamicMapping.h"
|
||||
#import "RKRelationshipMapping.h"
|
||||
|
||||
#if !__has_feature(objc_arc)
|
||||
#error RestKit must be built with ARC.
|
||||
@@ -81,17 +83,87 @@ static RKRequestDescriptor *RKRequestDescriptorFromArrayMatchingObject(NSArray *
|
||||
}
|
||||
|
||||
/**
|
||||
Returns `YES` if the given array of `RKResponseDescriptor` objects contains an `RKEntityMapping`.
|
||||
Visits all mappings accessible via relationships or dynamic mapping in an object graph starting from a given mapping.
|
||||
*/
|
||||
@interface RKMappingGraphVisitor : NSObject
|
||||
|
||||
@property (nonatomic, readonly) NSSet *mappings;
|
||||
|
||||
- (id)initWithMapping:(RKMapping *)mapping;
|
||||
|
||||
@end
|
||||
|
||||
@interface RKMappingGraphVisitor ()
|
||||
@property (nonatomic, readwrite) NSMutableSet *mutableMappings;
|
||||
@end
|
||||
|
||||
@implementation RKMappingGraphVisitor
|
||||
|
||||
- (id)initWithMapping:(RKMapping *)mapping
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.mutableMappings = [NSMutableSet set];
|
||||
[self visitMapping:mapping];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSSet *)mappings
|
||||
{
|
||||
return self.mutableMappings;
|
||||
}
|
||||
|
||||
- (void)visitMapping:(RKMapping *)mapping
|
||||
{
|
||||
if ([self.mappings containsObject:mapping]) return;
|
||||
[self.mutableMappings addObject:mapping];
|
||||
|
||||
if ([mapping isKindOfClass:[RKDynamicMapping class]]) {
|
||||
RKDynamicMapping *dynamicMapping = (RKDynamicMapping *)mapping;
|
||||
for (RKMapping *nestedMapping in dynamicMapping.objectMappings) {
|
||||
[self visitMapping:nestedMapping];
|
||||
}
|
||||
} else if ([mapping isKindOfClass:[RKObjectMapping class]]) {
|
||||
RKObjectMapping *objectMapping = (RKObjectMapping *)mapping;
|
||||
for (RKRelationshipMapping *relationshipMapping in objectMapping.relationshipMappings) {
|
||||
[self visitMapping:relationshipMapping.mapping];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
Returns `YES` if the given array of `RKResponseDescriptor` objects contains an `RKEntityMapping` anywhere in its object graph.
|
||||
|
||||
@param responseDescriptor An array of `RKResponseDescriptor` objects.
|
||||
@return `YES` if the `mapping` property of any of the response descriptor objects in the given array is an instance of `RKEntityMapping`, else `NO`.
|
||||
*/
|
||||
static BOOL RKDoesArrayOfResponseDescriptorsContainEntityMapping(NSArray *responseDescriptors)
|
||||
{
|
||||
// Visit all mappings accessible from the object graphs of all response descriptors
|
||||
NSMutableSet *accessibleMappings = [NSMutableSet set];
|
||||
for (RKResponseDescriptor *responseDescriptor in responseDescriptors) {
|
||||
if ([responseDescriptor.mapping isKindOfClass:[RKEntityMapping class]]) {
|
||||
if (! [accessibleMappings containsObject:responseDescriptor.mapping]) {
|
||||
RKMappingGraphVisitor *graphVisitor = [[RKMappingGraphVisitor alloc] initWithMapping:responseDescriptor.mapping];
|
||||
[accessibleMappings unionSet:graphVisitor.mappings];
|
||||
}
|
||||
}
|
||||
|
||||
// Enumerate all mappings and search for an `RKEntityMapping`
|
||||
for (RKMapping *mapping in accessibleMappings) {
|
||||
if ([mapping isKindOfClass:[RKEntityMapping class]]) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
if ([mapping isKindOfClass:[RKDynamicMapping class]]) {
|
||||
RKDynamicMapping *dynamicMapping = (RKDynamicMapping *)mapping;
|
||||
if ([dynamicMapping.objectMappings count] == 0) {
|
||||
// Likely means that there is a representation block, assume `YES`
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NO;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
// Cloned from AFStringFromIndexSet -- method should be non-static for reuse
|
||||
static NSString *RKStringFromIndexSet(NSIndexSet *indexSet) {
|
||||
NSCParameterAssert(indexSet);
|
||||
NSMutableString *string = [NSMutableString string];
|
||||
|
||||
NSRange range = NSMakeRange([indexSet firstIndex], 1);
|
||||
@@ -80,7 +81,7 @@ static NSString *RKStringFromIndexSet(NSIndexSet *indexSet) {
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"<%@: %p pathPattern=%@ keyPath=%@ statusCodes=%@ : %@>",
|
||||
NSStringFromClass([self class]), self, self.pathPattern, self.keyPath, RKStringFromIndexSet(self.statusCodes), self.mapping];
|
||||
NSStringFromClass([self class]), self, self.pathPattern, self.keyPath, self.statusCodes ? RKStringFromIndexSet(self.statusCodes) : self.statusCodes, self.mapping];
|
||||
}
|
||||
|
||||
- (BOOL)matchesPath:(NSString *)path
|
||||
|
||||
@@ -25,3 +25,4 @@
|
||||
#import "RKObjectParameterization.h"
|
||||
#import "RKMappingResult.h"
|
||||
#import "RKMapperOperation.h"
|
||||
#import "RKDynamicMapping.h"
|
||||
@@ -25,6 +25,7 @@
|
||||
#import "RKHuman.h"
|
||||
#import "RKCat.h"
|
||||
#import "RKObjectMapperTestModel.h"
|
||||
#import "RKDynamicMapping.h"
|
||||
|
||||
@interface RKSubclassedTestModel : RKObjectMapperTestModel
|
||||
@end
|
||||
@@ -526,6 +527,76 @@
|
||||
expect(dictionary).to.equal(@{ @"subclassed": @{ @"age": @(30) } });
|
||||
}
|
||||
|
||||
- (void)testThatResponseDescriptorWithUnmanagedMappingTriggersCreationOfObjectRequestOperation
|
||||
{
|
||||
RKObjectMapping *vanillaMapping = [RKObjectMapping requestMapping];
|
||||
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:vanillaMapping pathPattern:nil keyPath:nil statusCodes:nil];
|
||||
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
|
||||
manager.managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
[manager addResponseDescriptor:responseDescriptor];
|
||||
RKObjectRequestOperation *objectRequestOperation = [manager appropriateObjectRequestOperationWithObject:nil method:RKRequestMethodGET path:@"/something" parameters:nil];
|
||||
expect(objectRequestOperation).to.beInstanceOf([RKObjectRequestOperation class]);
|
||||
}
|
||||
|
||||
- (void)testThatResponseDescriptorWithDynamicMappingContainingEntityMappingsTriggersCreationOfManagedObjectRequestOperation
|
||||
{
|
||||
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:_objectManager.managedObjectStore];
|
||||
RKDynamicMapping *dynamicMapping = [RKDynamicMapping new];
|
||||
[dynamicMapping setObjectMapping:humanMapping whenValueOfKeyPath:@"whatever" isEqualTo:@"whatever"];
|
||||
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:dynamicMapping pathPattern:nil keyPath:nil statusCodes:nil];
|
||||
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
|
||||
manager.managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
[manager addResponseDescriptor:responseDescriptor];
|
||||
RKObjectRequestOperation *objectRequestOperation = [manager appropriateObjectRequestOperationWithObject:nil method:RKRequestMethodGET path:@"/something" parameters:nil];
|
||||
expect(objectRequestOperation).to.beInstanceOf([RKManagedObjectRequestOperation class]);
|
||||
}
|
||||
|
||||
- (void)testThatResponseDescriptorWithDynamicMappingUsingABlockTriggersCreationOfManagedObjectRequestOperation
|
||||
{
|
||||
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:_objectManager.managedObjectStore];
|
||||
RKDynamicMapping *dynamicMapping = [RKDynamicMapping new];
|
||||
[dynamicMapping setObjectMappingForRepresentationBlock:^RKObjectMapping *(id representation) {
|
||||
return humanMapping;
|
||||
}];
|
||||
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:dynamicMapping pathPattern:nil keyPath:nil statusCodes:nil];
|
||||
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
|
||||
manager.managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
[manager addResponseDescriptor:responseDescriptor];
|
||||
RKObjectRequestOperation *objectRequestOperation = [manager appropriateObjectRequestOperationWithObject:nil method:RKRequestMethodGET path:@"/something" parameters:nil];
|
||||
expect(objectRequestOperation).to.beInstanceOf([RKManagedObjectRequestOperation class]);
|
||||
}
|
||||
|
||||
- (void)testThatResponseDescriptorWithUnmanagedMappingContainingRelationshipMappingWithEntityMappingsTriggersCreationOfManagedObjectRequestOperation
|
||||
{
|
||||
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:_objectManager.managedObjectStore];
|
||||
RKObjectMapping *objectMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
|
||||
[objectMapping addRelationshipMappingWithSourceKeyPath:@"relationship" mapping:humanMapping];
|
||||
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:objectMapping pathPattern:nil keyPath:nil statusCodes:nil];
|
||||
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
|
||||
manager.managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
[manager addResponseDescriptor:responseDescriptor];
|
||||
RKObjectRequestOperation *objectRequestOperation = [manager appropriateObjectRequestOperationWithObject:nil method:RKRequestMethodGET path:@"/something" parameters:nil];
|
||||
expect(objectRequestOperation).to.beInstanceOf([RKManagedObjectRequestOperation class]);
|
||||
}
|
||||
|
||||
- (void)testThatResponseDescriptorWithUnmanagedMappingContainingRelationshipMappingWithEntityMappingsDeepWithinObjectGraphTriggersCreationOfManagedObjectRequestOperation
|
||||
{
|
||||
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:_objectManager.managedObjectStore];
|
||||
RKObjectMapping *objectMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
|
||||
[objectMapping addRelationshipMappingWithSourceKeyPath:@"relationship" mapping:humanMapping];
|
||||
RKObjectMapping *objectMapping2 = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
|
||||
[objectMapping2 addRelationshipMappingWithSourceKeyPath:@"relationship" mapping:objectMapping];
|
||||
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:objectMapping2 pathPattern:nil keyPath:nil statusCodes:nil];
|
||||
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://restkit.org"]];
|
||||
manager.managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
[manager addResponseDescriptor:responseDescriptor];
|
||||
RKObjectRequestOperation *objectRequestOperation = [manager appropriateObjectRequestOperationWithObject:nil method:RKRequestMethodGET path:@"/something" parameters:nil];
|
||||
expect(objectRequestOperation).to.beInstanceOf([RKManagedObjectRequestOperation class]);
|
||||
}
|
||||
|
||||
// Test with relationship 2 levels deep
|
||||
// Test with recursive relationships
|
||||
|
||||
//- (void)testShouldHandleConnectionFailures
|
||||
//{
|
||||
// NSString *localBaseURL = [NSString stringWithFormat:@"http://127.0.0.1:3001"];
|
||||
|
||||
Reference in New Issue
Block a user