Permalink
Browse files

Merge branch 'release/0.20.0-pre6'

  • Loading branch information...
2 parents 9103b9b + ee00e59 commit 22dd9ab40db337cba60f7ce0937d94c75c0ce040 @blakewatters blakewatters committed Jan 4, 2013
Showing with 2,105 additions and 723 deletions.
  1. +2 −2 Code/CoreData/RKConnectionDescription.h
  2. +2 −2 Code/CoreData/RKConnectionDescription.m
  3. +1 −1 Code/CoreData/RKEntityByAttributeCache.h
  4. +1 −1 Code/CoreData/RKEntityCache.h
  5. +12 −1 Code/CoreData/RKEntityMapping.h
  6. +3 −3 Code/CoreData/RKEntityMapping.m
  7. +1 −1 Code/CoreData/RKInMemoryManagedObjectCache.h
  8. +2 −2 Code/CoreData/RKManagedObjectImporter.h
  9. +1 −1 Code/CoreData/RKManagedObjectMappingOperationDataSource.h
  10. +92 −5 Code/CoreData/RKManagedObjectMappingOperationDataSource.m
  11. +3 −3 Code/CoreData/RKManagedObjectStore.h
  12. +2 −2 Code/CoreData/RKManagedObjectStore.m
  13. +1 −1 Code/CoreData/RKRelationshipConnectionOperation.h
  14. +2 −2 Code/CoreData/RKRelationshipConnectionOperation.m
  15. +4 −4 Code/Network/RKHTTPRequestOperation.m
  16. +244 −80 Code/Network/RKManagedObjectRequestOperation.m
  17. +15 −6 Code/Network/RKObjectManager.h
  18. +98 −37 Code/Network/RKObjectManager.m
  19. +2 −2 Code/Network/RKObjectRequestOperation.h
  20. +14 −0 Code/Network/RKObjectRequestOperation.m
  21. +21 −6 Code/Network/RKPaginator.h
  22. +25 −20 Code/Network/RKPaginator.m
  23. +9 −1 Code/Network/RKResponseMapperOperation.h
  24. +12 −5 Code/Network/RKResponseMapperOperation.m
  25. +1 −1 Code/Network/RKRouter.h
  26. +1 −1 Code/ObjectMapping/RKAttributeMapping.m
  27. +57 −18 Code/ObjectMapping/RKDynamicMapping.h
  28. +25 −10 Code/ObjectMapping/RKDynamicMapping.m
  29. +0 −67 Code/ObjectMapping/RKDynamicMappingMatcher.h
  30. +0 −49 Code/ObjectMapping/RKDynamicMappingMatcher.m
  31. +1 −1 Code/ObjectMapping/RKMapperOperation.h
  32. +1 −1 Code/ObjectMapping/RKMappingOperation.h
  33. +63 −8 Code/ObjectMapping/RKMappingOperation.m
  34. +1 −1 Code/ObjectMapping/RKMappingResult.h
  35. +43 −11 Code/ObjectMapping/RKObjectMapping.h
  36. +4 −7 Code/ObjectMapping/RKObjectMapping.m
  37. +75 −0 Code/ObjectMapping/RKObjectMappingMatcher.h
  38. +123 −0 Code/ObjectMapping/RKObjectMappingMatcher.m
  39. +1 −0 Code/Support/RestKit-Prefix.pch
  40. +4 −0 Code/Testing.h
  41. +5 −1 Code/Testing/RKConnectionTestExpectation.h
  42. +5 −2 Code/Testing/RKConnectionTestExpectation.m
  43. +5 −2 Code/Testing/RKMappingTest.h
  44. +10 −4 Code/Testing/RKMappingTest.m
  45. +4 −2 README.md
  46. +3 −3 RestKit.podspec
  47. +33 −18 RestKit.xcodeproj/project.pbxproj
  48. +61 −0 Tests/Fixtures/JSON/humans/nested_self_referential.json
  49. +26 −0 Tests/Fixtures/JSON/humans/self_referential.json
  50. +12 −1 Tests/Fixtures/JSON/humans/with_to_one_relationship.json
  51. +4 −1 Tests/Fixtures/JSON/user.json
  52. +2 −2 Tests/Logic/CoreData/RKEntityMappingTest.m
  53. +45 −0 Tests/Logic/CoreData/RKManagedObjectMappingOperationDataSourceTest.m
  54. +191 −1 Tests/Logic/Network/RKManagedObjectRequestOperationTest.m
  55. +21 −0 Tests/Logic/Network/RKObjectRequestOperationTest.m
  56. +1 −1 Tests/Logic/Network/RKRequestDescriptorTest.m
  57. +146 −0 Tests/Logic/ObjectMapping/RKDynamicMappingTest.m
  58. +0 −89 Tests/Logic/ObjectMapping/RKDynamicObjectMappingTest.m
  59. +229 −213 Tests/Logic/ObjectMapping/RKObjectManagerTest.m
  60. +23 −6 Tests/Logic/ObjectMapping/RKObjectMappingNextGenTest.m
  61. +21 −0 Tests/Logic/ObjectMapping/RKObjectMappingTest.m
  62. +18 −3 Tests/Logic/ObjectMapping/RKObjectParameterizationTest.m
  63. +30 −6 Tests/Logic/ObjectMapping/RKPaginatorTest.m
  64. +224 −0 Tests/Logic/Testing/RKMappingTestTest.m
  65. BIN Tests/Models/Data Model.xcdatamodel/elements
  66. BIN Tests/Models/Data Model.xcdatamodel/layout
  67. +2 −0 Tests/Models/RKTestUser.h
  68. +7 −0 Tests/Models/RKTestUser.m
  69. +6 −3 Tests/Server/server.rb
  70. +1 −1 VERSION
  71. +1 −1 Vendor/AFNetworking
@@ -88,7 +88,7 @@
@param sourceToDestinationEntityAttributes A dictionary specifying how attributes on the source entity correspond to attributes on the destination entity.
@return The receiver, initialized with the given relationship and attributes.
*/
-- (instancetype)initWithRelationship:(NSRelationshipDescription *)relationship attributes:(NSDictionary *)sourceToDestinationEntityAttributes;
+- (id)initWithRelationship:(NSRelationshipDescription *)relationship attributes:(NSDictionary *)sourceToDestinationEntityAttributes;
/**
The dictionary of attributes specifying how attributes on the source entity for the relationship correspond to attributes on the destination entity.
@@ -115,7 +115,7 @@
@param keyPath The key path from which to read the value that is to be set for the relationship.
@return The receiver, initialized with the given relationship and key path.
*/
-- (instancetype)initWithRelationship:(NSRelationshipDescription *)relationship keyPath:(NSString *)keyPath;
+- (id)initWithRelationship:(NSRelationshipDescription *)relationship keyPath:(NSString *)keyPath;
/**
The key path that is to be evaluated to obtain the value for the relationship.
@@ -44,7 +44,7 @@ @interface RKConnectionDescription ()
@implementation RKConnectionDescription
-- (instancetype)initWithRelationship:(NSRelationshipDescription *)relationship attributes:(NSDictionary *)attributes
+- (id)initWithRelationship:(NSRelationshipDescription *)relationship attributes:(NSDictionary *)attributes
{
NSParameterAssert(relationship);
NSParameterAssert(attributes);
@@ -63,7 +63,7 @@ - (instancetype)initWithRelationship:(NSRelationshipDescription *)relationship a
return self;
}
-- (instancetype)initWithRelationship:(NSRelationshipDescription *)relationship keyPath:(NSString *)keyPath
+- (id)initWithRelationship:(NSRelationshipDescription *)relationship keyPath:(NSString *)keyPath
{
NSParameterAssert(relationship);
NSParameterAssert(keyPath);
@@ -46,7 +46,7 @@
@return The receiver, initialized with the given entity, attribute, and managed object
context.
*/
-- (instancetype)initWithEntity:(NSEntityDescription *)entity attributes:(NSArray *)attributeNames managedObjectContext:(NSManagedObjectContext *)context;
+- (id)initWithEntity:(NSEntityDescription *)entity attributes:(NSArray *)attributeNames managedObjectContext:(NSManagedObjectContext *)context;
///-----------------------------
/// @name Getting Cache Identity
@@ -43,7 +43,7 @@
@param context The managed object context containing objects to be cached.
@returns self, initialized with context.
*/
-- (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)context;
+- (id)initWithManagedObjectContext:(NSManagedObjectContext *)context;
/**
The managed object context with which the receiver is associated.
@@ -68,7 +68,7 @@
@param entity An entity with which to initialize the receiver.
@returns The receiver, initialized with the given entity.
*/
-- (instancetype)initWithEntity:(NSEntityDescription *)entity;
+- (id)initWithEntity:(NSEntityDescription *)entity;
/**
A convenience initializer that creates and returns an entity mapping for the entity with the given name in
@@ -177,6 +177,17 @@
*/
- (RKConnectionDescription *)connectionForRelationship:(id)relationshipOrName;
+///------------------------------------
+/// @name Flagging Objects for Deletion
+///------------------------------------
+
+/**
+ A predicate that identifies objects for the receiver's entity that are to be deleted from the local store.
+
+ This property provides support for local deletion of managed objects mapped as a 'tombstone' record from the source representation.
+ */
+@property (nonatomic, copy) NSPredicate *deletionPredicate;
+
///------------------------------------------
/// @name Retrieving Default Attribute Values
///------------------------------------------
@@ -20,7 +20,7 @@
#import "RKEntityMapping.h"
#import "RKManagedObjectStore.h"
-#import "RKDynamicMappingMatcher.h"
+#import "RKObjectMappingMatcher.h"
#import "RKPropertyInspector+CoreData.h"
#import "RKLog.h"
#import "RKRelationshipMapping.h"
@@ -153,7 +153,7 @@ + (instancetype)mappingForEntityForName:(NSString *)entityName inManagedObjectSt
return [[self alloc] initWithEntity:entity];
}
-- (instancetype)initWithEntity:(NSEntityDescription *)entity
+- (id)initWithEntity:(NSEntityDescription *)entity
{
NSAssert(entity, @"Cannot initialize an RKEntityMapping without an entity. Maybe you want RKObjectMapping instead?");
Class objectClass = NSClassFromString([entity managedObjectClassName]);
@@ -167,7 +167,7 @@ - (instancetype)initWithEntity:(NSEntityDescription *)entity
return self;
}
-- (instancetype)initWithClass:(Class)objectClass
+- (id)initWithClass:(Class)objectClass
{
self = [super initWithClass:objectClass];
if (self) {
@@ -35,6 +35,6 @@
@param managedObjectContext The managed object context with which to initialize the receiver.
@return The receiver, initialized with the given managed object context.
*/
-- (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext;
+- (id)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext;
@end
@@ -55,7 +55,7 @@
@warning As this initialization code path is typical for generating seed databases, the value of
`resetsStoreBeforeImporting` is initialized to **YES**.
*/
-- (instancetype)initWithManagedObjectModel:(NSManagedObjectModel *)managedObjectModel storePath:(NSString *)storePath;
+- (id)initWithManagedObjectModel:(NSManagedObjectModel *)managedObjectModel storePath:(NSString *)storePath;
/**
Initializes the receiver with a given persistent store in which to persist imported managed objects.
@@ -69,7 +69,7 @@
managed object model are determined from the given persistent store and a new managed object context with
the private queue concurrency type is constructed.
*/
-- (instancetype)initWithPersistentStore:(NSPersistentStore *)persistentStore;
+- (id)initWithPersistentStore:(NSPersistentStore *)persistentStore;
/**
A Boolean value indicating whether existing managed objects in the persistent store should
@@ -42,7 +42,7 @@
@param managedObjectCache The managed object cache used by the receiver to find existing object instances by their identification attributes.
@return The receiver, initialized with the given managed object context and managed objet cache.
*/
-- (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext cache:(id<RKManagedObjectCaching>)managedObjectCache;
+- (id)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext cache:(id<RKManagedObjectCaching>)managedObjectCache;
///-----------------------------------------------------
/// @name Accessing the Managed Object Context and Cache
@@ -18,22 +18,26 @@
// limitations under the License.
//
+#import <objc/runtime.h>
#import "RKManagedObjectMappingOperationDataSource.h"
#import "RKObjectMapping.h"
#import "RKEntityMapping.h"
#import "RKLog.h"
#import "RKManagedObjectStore.h"
#import "RKMappingOperation.h"
-#import "RKDynamicMappingMatcher.h"
+#import "RKObjectMappingMatcher.h"
#import "RKManagedObjectCaching.h"
#import "RKRelationshipConnectionOperation.h"
#import "RKMappingErrors.h"
#import "RKValueTransformers.h"
#import "RKRelationshipMapping.h"
#import "RKObjectUtilities.h"
+#import "NSManagedObject+RKAdditions.h"
extern NSString * const RKObjectMappingNestingAttributeKeyName;
+static char kRKManagedObjectMappingOperationDataSourceAssociatedObjectKey;
+
id RKTransformedValueWithClass(id value, Class destinationType, NSValueTransformer *dateToStringValueTransformer);
NSArray *RKApplyNestingAttributeValueToMappings(NSString *attributeName, id value, NSArray *propertyMappings);
@@ -117,6 +121,58 @@ static id RKValueForAttributeMappingInRepresentation(RKAttributeMapping *attribu
return entityIdentifierAttributes;
}
+@interface RKManagedObjectDeletionOperation : NSOperation
+
+- (id)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext;
+- (void)addEntityMapping:(RKEntityMapping *)entityMapping;
+@end
+
+@interface RKManagedObjectDeletionOperation ()
+@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;
+@property (nonatomic, strong) NSMutableSet *entityMappings;
+@end
+
+@implementation RKManagedObjectDeletionOperation
+
+- (id)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext
+{
+ self = [self init];
+ if (self) {
+ self.managedObjectContext = managedObjectContext;
+ self.entityMappings = [NSMutableSet new];
+ }
+ return self;
+}
+
+- (void)addEntityMapping:(RKEntityMapping *)entityMapping
+{
+ if (! entityMapping.deletionPredicate) return;
+ [self.entityMappings addObject:entityMapping];
+}
+
+- (void)main
+{
+ [self.managedObjectContext performBlockAndWait:^{
+ NSMutableSet *objectsToDelete = [NSMutableSet set];
+ for (RKEntityMapping *entityMapping in self.entityMappings) {
+ NSFetchRequest *fetchRequest = [NSFetchRequest alloc];
+ [fetchRequest setEntity:entityMapping.entity];
+ [fetchRequest setPredicate:entityMapping.deletionPredicate];
+ NSError *error = nil;
+ NSArray *fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
+ if (fetchedObjects) {
+ [objectsToDelete addObjectsFromArray:fetchedObjects];
+ }
+ }
+
+ for (NSManagedObject *managedObject in objectsToDelete) {
+ [self.managedObjectContext deleteObject:managedObject];
+ }
+ }];
+}
+
+@end
+
// Set Logging Component
#undef RKLogComponent
#define RKLogComponent RKlcl_cRestKitCoreData
@@ -126,11 +182,12 @@ static id RKValueForAttributeMappingInRepresentation(RKAttributeMapping *attribu
@interface RKManagedObjectMappingOperationDataSource ()
@property (nonatomic, strong, readwrite) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, strong, readwrite) id<RKManagedObjectCaching> managedObjectCache;
+@property (nonatomic, strong) NSMutableArray *deletionPredicates;
@end
@implementation RKManagedObjectMappingOperationDataSource
-- (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext cache:(id<RKManagedObjectCaching>)managedObjectCache
+- (id)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext cache:(id<RKManagedObjectCaching>)managedObjectCache
{
NSParameterAssert(managedObjectContext);
@@ -169,7 +226,7 @@ - (id)mappingOperation:(RKMappingOperation *)mappingOperation targetObjectForRep
"Unable to update existing object instances by identification attributes. Duplicate objects may be created.");
}
- // If we have found the entity identifier attributes, try to find an existing instance to update
+ // If we have found the entity identification attributes, try to find an existing instance to update
NSEntityDescription *entity = [entityMapping entity];
NSManagedObject *managedObject = nil;
if ([entityIdentifierAttributes count]) {
@@ -187,8 +244,7 @@ - (id)mappingOperation:(RKMappingOperation *)mappingOperation targetObjectForRep
}
if (managedObject == nil) {
- managedObject = [[NSManagedObject alloc] initWithEntity:entity
- insertIntoManagedObjectContext:self.managedObjectContext];
+ managedObject = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:self.managedObjectContext];
[managedObject setValuesForKeysWithDictionary:entityIdentifierAttributes];
if ([self.managedObjectCache respondsToSelector:@selector(didCreateObject:)]) {
@@ -220,6 +276,16 @@ - (BOOL)commitChangesForMappingOperation:(RKMappingOperation *)mappingOperation
if ([mappingOperation.objectMapping isKindOfClass:[RKEntityMapping class]]) {
[self emitDeadlockWarningIfNecessary];
+ // Validate unsaved objects
+ if ([mappingOperation.destinationObject isKindOfClass:[NSManagedObject class]] && [(NSManagedObject *)mappingOperation.destinationObject isNew]) {
+ NSError *validationError = nil;
+ if (! [(NSManagedObject *)mappingOperation.destinationObject validateForInsert:&validationError]) {
+ RKLogDebug(@"Unsaved NSManagedObject failed `validateForInsert:` - Deleting object from context: %@", validationError);
+ [self.managedObjectContext deleteObject:mappingOperation.destinationObject];
+ return YES;
+ }
+ }
+
NSArray *connections = [(RKEntityMapping *)mappingOperation.objectMapping connections];
if ([connections count] > 0 && self.managedObjectCache == nil) {
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: @"Cannot map an entity mapping that contains connection mappings with a data source whose managed object cache is nil." };
@@ -246,6 +312,27 @@ - (BOOL)commitChangesForMappingOperation:(RKMappingOperation *)mappingOperation
[operationQueue addOperation:operation];
RKLogTrace(@"Enqueued %@ dependent upon parent operation %@ to operation queue %@", operation, self.parentOperation, operationQueue);
}
+
+ // Handle tombstone deletion by predicate
+ if ([(RKEntityMapping *)mappingOperation.objectMapping deletionPredicate]) {
+ RKManagedObjectDeletionOperation *deletionOperation = nil;
+ if (self.parentOperation) {
+ // Attach a deletion operation for execution after the parent operation completes
+ deletionOperation = (RKManagedObjectDeletionOperation *)objc_getAssociatedObject(self.parentOperation, &kRKManagedObjectMappingOperationDataSourceAssociatedObjectKey);
+ if (! deletionOperation) {
+ deletionOperation = [[RKManagedObjectDeletionOperation alloc] initWithManagedObjectContext:self.managedObjectContext];
+ objc_setAssociatedObject(self.parentOperation, &kRKManagedObjectMappingOperationDataSourceAssociatedObjectKey, deletionOperation, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+ [deletionOperation addDependency:self.parentOperation];
+ NSOperationQueue *operationQueue = self.operationQueue ?: [NSOperationQueue currentQueue];
+ [operationQueue addOperation:deletionOperation];
+ }
+ [deletionOperation addEntityMapping:(RKEntityMapping *)mappingOperation.objectMapping];
+ } else {
+ deletionOperation = [[RKManagedObjectDeletionOperation alloc] initWithManagedObjectContext:self.managedObjectContext];
+ [deletionOperation addEntityMapping:(RKEntityMapping *)mappingOperation.objectMapping];
+ [deletionOperation start];
+ }
+ }
}
return YES;
@@ -76,7 +76,7 @@
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
*/
-- (instancetype)initWithManagedObjectModel:(NSManagedObjectModel *)managedObjectModel;
+- (id)initWithManagedObjectModel:(NSManagedObjectModel *)managedObjectModel;
/**
Initializes the receiver with an existing persistent store coordinator.
@@ -88,7 +88,7 @@
@param persistentStoreCoordinator The persistent store coordinator with which to initialize the receiver.
@return The receiver, initialized with the managed object model of the given persistent store coordinator and the persistent store coordinator.
*/
-- (instancetype)initWithPersistentStoreCoordinator:(NSPersistentStoreCoordinator *)persistentStoreCoordinator;
+- (id)initWithPersistentStoreCoordinator:(NSPersistentStoreCoordinator *)persistentStoreCoordinator;
/**
Initializes the receiver with a managed object model obtained by merging the models from all of the application's non-framework bundles.
@@ -98,7 +98,7 @@
@warning Obtaining a managed object model by merging all bundles may result in an application error if versioned object models are in use.
*/
-- (instancetype)init;
+- (id)init;
///-----------------------------------------------------------------------------
/// @name Configuring Persistent Stores
@@ -57,7 +57,7 @@ + (void)setDefaultStore:(RKManagedObjectStore *)managedObjectStore
}
}
-- (instancetype)initWithManagedObjectModel:(NSManagedObjectModel *)managedObjectModel
+- (id)initWithManagedObjectModel:(NSManagedObjectModel *)managedObjectModel
{
self = [super init];
if (self) {
@@ -73,7 +73,7 @@ - (instancetype)initWithManagedObjectModel:(NSManagedObjectModel *)managedObject
return self;
}
-- (instancetype)initWithPersistentStoreCoordinator:(NSPersistentStoreCoordinator *)persistentStoreCoordinator
+- (id)initWithPersistentStoreCoordinator:(NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
self = [self initWithManagedObjectModel:persistentStoreCoordinator.managedObjectModel];
if (self) {
@@ -44,7 +44,7 @@
@param managedObjectCache The managed object cache from which to attempt to fetch a matching object to satisfy the connection.
@return The receiver, initialized with the given managed object, connection mapping, and managed object cache.
*/
-- (instancetype)initWithManagedObject:(NSManagedObject *)managedObject
+- (id)initWithManagedObject:(NSManagedObject *)managedObject
connection:(RKConnectionDescription *)connection
managedObjectCache:(id<RKManagedObjectCaching>)managedObjectCache;
@@ -24,7 +24,7 @@
#import "RKEntityMapping.h"
#import "RKLog.h"
#import "RKManagedObjectCaching.h"
-#import "RKDynamicMappingMatcher.h"
+#import "RKObjectMappingMatcher.h"
#import "RKErrors.h"
#import "RKObjectUtilities.h"
@@ -70,7 +70,7 @@ @interface RKRelationshipConnectionOperation ()
@implementation RKRelationshipConnectionOperation
-- (instancetype)initWithManagedObject:(NSManagedObject *)managedObject
+- (id)initWithManagedObject:(NSManagedObject *)managedObject
connection:(RKConnectionDescription *)connection
managedObjectCache:(id<RKManagedObjectCaching>)managedObjectCache;
{
Oops, something went wrong. Retry.

0 comments on commit 22dd9ab

Please sign in to comment.