Skip to content

Commit

Permalink
Merge branch 'release/0.20.0-pre5'
Browse files Browse the repository at this point in the history
  • Loading branch information
blakewatters committed Dec 27, 2012
2 parents 3c84765 + baa9f62 commit 9103b9b
Show file tree
Hide file tree
Showing 87 changed files with 1,905 additions and 540 deletions.
18 changes: 15 additions & 3 deletions Code/CoreData/RKConnectionDescription.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
- (id)initWithRelationship:(NSRelationshipDescription *)relationship attributes:(NSDictionary *)sourceToDestinationEntityAttributes;
- (instancetype)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.
Expand All @@ -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.
*/
- (id)initWithRelationship:(NSRelationshipDescription *)relationship keyPath:(NSString *)keyPath;
- (instancetype)initWithRelationship:(NSRelationshipDescription *)relationship keyPath:(NSString *)keyPath;

/**
The key path that is to be evaluated to obtain the value for the relationship.
Expand Down Expand Up @@ -144,9 +144,21 @@
/// @name Setting the Predicate
///----------------------------

/**
Returns a Boolean value that determines if the connection includes subentities. If `NO`, then the connection will only be established to objects of exactly the entity specified by the relationship's entity. If `YES`, then the connection will be established to all objects of the relationship's entity and all subentities.
**Default**: `YES`
*/
@property (nonatomic, assign) BOOL includesSubentities;

/**
An optional predicate for conditionally evaluating the connection based on the state of the source object.
*/
@property (nonatomic, strong) NSPredicate *sourcePredicate;

/**
An optional predicate for filtering objects to be connected.
*/
@property (nonatomic, copy) NSPredicate *predicate;
@property (nonatomic, copy) NSPredicate *destinationPredicate;

@end
7 changes: 4 additions & 3 deletions Code/CoreData/RKConnectionDescription.m
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ @interface RKConnectionDescription ()

@implementation RKConnectionDescription

- (id)initWithRelationship:(NSRelationshipDescription *)relationship attributes:(NSDictionary *)attributes
- (instancetype)initWithRelationship:(NSRelationshipDescription *)relationship attributes:(NSDictionary *)attributes
{
NSParameterAssert(relationship);
NSParameterAssert(attributes);
Expand All @@ -58,11 +58,12 @@ - (id)initWithRelationship:(NSRelationshipDescription *)relationship attributes:
if (self) {
self.relationship = relationship;
self.attributes = attributes;
self.includesSubentities = YES;
}
return self;
}

- (id)initWithRelationship:(NSRelationshipDescription *)relationship keyPath:(NSString *)keyPath
- (instancetype)initWithRelationship:(NSRelationshipDescription *)relationship keyPath:(NSString *)keyPath
{
NSParameterAssert(relationship);
NSParameterAssert(keyPath);
Expand All @@ -79,7 +80,7 @@ - (id)init
if ([self class] == [RKConnectionDescription class]) {
@throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:[NSString stringWithFormat:@"%@ Failed to call designated initializer. "
"Invoke initWithRelationship:sourceKeyPath:destinationKeyPath:matcher: instead.",
"Invoke initWithRelationship:attributes: instead.",
NSStringFromClass([self class])]
userInfo:nil];
}
Expand Down
2 changes: 1 addition & 1 deletion Code/CoreData/RKEntityByAttributeCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
@return The receiver, initialized with the given entity, attribute, and managed object
context.
*/
- (id)initWithEntity:(NSEntityDescription *)entity attributes:(NSArray *)attributeNames managedObjectContext:(NSManagedObjectContext *)context;
- (instancetype)initWithEntity:(NSEntityDescription *)entity attributes:(NSArray *)attributeNames managedObjectContext:(NSManagedObjectContext *)context;

///-----------------------------
/// @name Getting Cache Identity
Expand Down
2 changes: 1 addition & 1 deletion Code/CoreData/RKEntityCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
@param context The managed object context containing objects to be cached.
@returns self, initialized with context.
*/
- (id)initWithManagedObjectContext:(NSManagedObjectContext *)context;
- (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)context;

/**
The managed object context with which the receiver is associated.
Expand Down
2 changes: 0 additions & 2 deletions Code/CoreData/RKEntityCache.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ @interface RKEntityCache ()

@implementation RKEntityCache


- (id)initWithManagedObjectContext:(NSManagedObjectContext *)context
{
NSAssert(context, @"Cannot initialize entity cache with a nil context");
Expand All @@ -45,7 +44,6 @@ - (id)init
return [self initWithManagedObjectContext:nil];
}


- (void)cacheObjectsForEntity:(NSEntityDescription *)entity byAttributes:(NSArray *)attributeNames
{
NSParameterAssert(entity);
Expand Down
4 changes: 2 additions & 2 deletions Code/CoreData/RKEntityMapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
@param entity An entity with which to initialize the receiver.
@returns The receiver, initialized with the given entity.
*/
- (id)initWithEntity:(NSEntityDescription *)entity;
- (instancetype)initWithEntity:(NSEntityDescription *)entity;

/**
A convenience initializer that creates and returns an entity mapping for the entity with the given name in
Expand All @@ -83,7 +83,7 @@
@param managedObjectStore A managed object store containing the managed object model in which an entity with the given name is defined.
@return A new entity mapping for the entity with the given name in the managed object model of the given managed object store.
*/
+ (id)mappingForEntityForName:(NSString *)entityName inManagedObjectStore:(RKManagedObjectStore *)managedObjectStore;
+ (instancetype)mappingForEntityForName:(NSString *)entityName inManagedObjectStore:(RKManagedObjectStore *)managedObjectStore;

///---------------------------
/// @name Accessing the Entity
Expand Down
49 changes: 26 additions & 23 deletions Code/CoreData/RKEntityMapping.m
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,27 @@

static NSArray *RKEntityIdentificationAttributesFromUserInfoOfEntity(NSEntityDescription *entity)
{
id userInfoValue = [[entity userInfo] valueForKey:RKEntityIdentificationAttributesUserInfoKey];
if (userInfoValue) {
NSArray *attributeNames = [userInfoValue isKindOfClass:[NSArray class]] ? userInfoValue : @[ userInfoValue ];
NSMutableArray *attributes = [NSMutableArray arrayWithCapacity:[attributeNames count]];
[attributeNames enumerateObjectsUsingBlock:^(NSString *attributeName, NSUInteger idx, BOOL *stop) {
if (! [attributeName isKindOfClass:[NSString class]]) {
[NSException raise:NSInvalidArgumentException format:@"Invalid value given in user info key '%@' of entity '%@': expected an `NSString` or `NSArray` of strings, instead got '%@' (%@)", RKEntityIdentificationAttributesUserInfoKey, [entity name], attributeName, [attributeName class]];
}

NSAttributeDescription *attribute = [[entity attributesByName] valueForKey:attributeName];
if (! attribute) {
[NSException raise:NSInvalidArgumentException format:@"Invalid identifier attribute specified in user info key '%@' of entity '%@': no attribue was found with the name '%@'", RKEntityIdentificationAttributesUserInfoKey, [entity name], attributeName];
}

[attributes addObject:attribute];
}];
return attributes;
}
do {
id userInfoValue = [[entity userInfo] valueForKey:RKEntityIdentificationAttributesUserInfoKey];
if (userInfoValue) {
NSArray *attributeNames = [userInfoValue isKindOfClass:[NSArray class]] ? userInfoValue : @[ userInfoValue ];
NSMutableArray *attributes = [NSMutableArray arrayWithCapacity:[attributeNames count]];
[attributeNames enumerateObjectsUsingBlock:^(NSString *attributeName, NSUInteger idx, BOOL *stop) {
if (! [attributeName isKindOfClass:[NSString class]]) {
[NSException raise:NSInvalidArgumentException format:@"Invalid value given in user info key '%@' of entity '%@': expected an `NSString` or `NSArray` of strings, instead got '%@' (%@)", RKEntityIdentificationAttributesUserInfoKey, [entity name], attributeName, [attributeName class]];
}

NSAttributeDescription *attribute = [[entity attributesByName] valueForKey:attributeName];
if (! attribute) {
[NSException raise:NSInvalidArgumentException format:@"Invalid identifier attribute specified in user info key '%@' of entity '%@': no attribue was found with the name '%@'", RKEntityIdentificationAttributesUserInfoKey, [entity name], attributeName];
}

[attributes addObject:attribute];
}];
return attributes;
}
entity = [entity superentity];
} while (entity);

return nil;
}
Expand Down Expand Up @@ -137,20 +140,20 @@ @implementation RKEntityMapping

@synthesize identificationAttributes = _identificationAttributes;

+ (id)mappingForClass:(Class)objectClass
+ (instancetype)mappingForClass:(Class)objectClass
{
@throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:[NSString stringWithFormat:@"You must provide a managedObjectStore. Invoke mappingForClass:inManagedObjectStore: instead."]
userInfo:nil];
}

+ (id)mappingForEntityForName:(NSString *)entityName inManagedObjectStore:(RKManagedObjectStore *)managedObjectStore
+ (instancetype)mappingForEntityForName:(NSString *)entityName inManagedObjectStore:(RKManagedObjectStore *)managedObjectStore
{
NSEntityDescription *entity = [[managedObjectStore.managedObjectModel entitiesByName] objectForKey:entityName];
return [[self alloc] initWithEntity:entity];
}

- (id)initWithEntity:(NSEntityDescription *)entity
- (instancetype)initWithEntity:(NSEntityDescription *)entity
{
NSAssert(entity, @"Cannot initialize an RKEntityMapping without an entity. Maybe you want RKObjectMapping instead?");
Class objectClass = NSClassFromString([entity managedObjectClassName]);
Expand All @@ -164,7 +167,7 @@ - (id)initWithEntity:(NSEntityDescription *)entity
return self;
}

- (id)initWithClass:(Class)objectClass
- (instancetype)initWithClass:(Class)objectClass
{
self = [super initWithClass:objectClass];
if (self) {
Expand Down Expand Up @@ -275,7 +278,7 @@ - (Class)classForKeyPath:(NSString *)keyPath
NSArray *components = [keyPath componentsSeparatedByString:@"."];
Class propertyClass = self.objectClass;
for (NSString *property in components) {
propertyClass = [[RKPropertyInspector sharedInspector] classForPropertyNamed:property ofClass:propertyClass];
propertyClass = [[RKPropertyInspector sharedInspector] classForPropertyNamed:property ofClass:propertyClass isPrimitive:nil];
if (! propertyClass) propertyClass = [[RKPropertyInspector sharedInspector] classForPropertyNamed:property ofEntity:self.entity];
if (! propertyClass) break;
}
Expand Down
2 changes: 1 addition & 1 deletion Code/CoreData/RKInMemoryManagedObjectCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
- (id)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext;
- (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext;

@end
4 changes: 2 additions & 2 deletions Code/CoreData/RKManagedObjectImporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
@warning As this initialization code path is typical for generating seed databases, the value of
`resetsStoreBeforeImporting` is initialized to **YES**.
*/
- (id)initWithManagedObjectModel:(NSManagedObjectModel *)managedObjectModel storePath:(NSString *)storePath;
- (instancetype)initWithManagedObjectModel:(NSManagedObjectModel *)managedObjectModel storePath:(NSString *)storePath;

/**
Initializes the receiver with a given persistent store in which to persist imported managed objects.
Expand All @@ -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.
*/
- (id)initWithPersistentStore:(NSPersistentStore *)persistentStore;
- (instancetype)initWithPersistentStore:(NSPersistentStore *)persistentStore;

/**
A Boolean value indicating whether existing managed objects in the persistent store should
Expand Down
2 changes: 1 addition & 1 deletion Code/CoreData/RKManagedObjectImporter.m
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ - (NSUInteger)importObjectsFromFileAtPath:(NSString *)path withMapping:(RKMappin
}

NSDictionary *mappingDictionary = @{ (keyPath ?: [NSNull null]) : mapping };
RKMapperOperation *mapper = [[RKMapperOperation alloc] initWithObject:parsedData mappingsDictionary:mappingDictionary];
RKMapperOperation *mapper = [[RKMapperOperation alloc] initWithRepresentation:parsedData mappingsDictionary:mappingDictionary];
mapper.mappingOperationDataSource = self.mappingOperationDataSource;
__block RKMappingResult *mappingResult;
[self.managedObjectContext performBlockAndWait:^{
Expand Down
2 changes: 1 addition & 1 deletion Code/CoreData/RKManagedObjectMappingOperationDataSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
- (id)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext cache:(id<RKManagedObjectCaching>)managedObjectCache;
- (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext cache:(id<RKManagedObjectCaching>)managedObjectCache;

///-----------------------------------------------------
/// @name Accessing the Managed Object Context and Cache
Expand Down
71 changes: 70 additions & 1 deletion Code/CoreData/RKManagedObjectMappingOperationDataSource.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#import "RKRelationshipConnectionOperation.h"
#import "RKMappingErrors.h"
#import "RKValueTransformers.h"
#import "RKRelationshipMapping.h"
#import "RKObjectUtilities.h"

extern NSString * const RKObjectMappingNestingAttributeKeyName;

Expand Down Expand Up @@ -128,19 +130,29 @@ @interface RKManagedObjectMappingOperationDataSource ()

@implementation RKManagedObjectMappingOperationDataSource

- (id)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext cache:(id<RKManagedObjectCaching>)managedObjectCache
- (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext cache:(id<RKManagedObjectCaching>)managedObjectCache
{
NSParameterAssert(managedObjectContext);

self = [self init];
if (self) {
self.managedObjectContext = managedObjectContext;
self.managedObjectCache = managedObjectCache;

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(updateCacheWithChangesFromContextWillSaveNotification:)
name:NSManagedObjectContextWillSaveNotification
object:managedObjectContext];
}

return self;
}

- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (id)mappingOperation:(RKMappingOperation *)mappingOperation targetObjectForRepresentation:(NSDictionary *)representation withMapping:(RKObjectMapping *)mapping
{
NSAssert(representation, @"Mappable data cannot be nil");
Expand Down Expand Up @@ -239,4 +251,61 @@ - (BOOL)commitChangesForMappingOperation:(RKMappingOperation *)mappingOperation
return YES;
}

// NOTE: In theory we should be able to use the userInfo dictionary, but the dictionary was coming in empty (12/18/2012)
- (void)updateCacheWithChangesFromContextWillSaveNotification:(NSNotification *)notification
{
NSSet *objectsToAdd = [[self.managedObjectContext insertedObjects] setByAddingObjectsFromSet:[self.managedObjectContext updatedObjects]];

__block BOOL success;
__block NSError *error = nil;
[self.managedObjectContext performBlockAndWait:^{
success = [self.managedObjectContext obtainPermanentIDsForObjects:[objectsToAdd allObjects] error:&error];
}];

if (! success) {
RKLogWarning(@"Failed obtaining permanent managed object ID's for %ld objects: the managed object cache was not updated and duplicate objects may be created.", (long) [objectsToAdd count]);
RKLogError(@"Obtaining permanent managed object IDs failed with error: %@", error);
return;
}

// Update the cache
if ([self.managedObjectCache respondsToSelector:@selector(didFetchObject:)]) {
for (NSManagedObject *managedObject in objectsToAdd) {
[self.managedObjectCache didFetchObject:managedObject];
}
}

if ([self.managedObjectCache respondsToSelector:@selector(didDeleteObject::)]) {
for (NSManagedObject *managedObject in [self.managedObjectContext deletedObjects]) {
[self.managedObjectCache didDeleteObject:managedObject];
}
}
}

- (BOOL)mappingOperation:(RKMappingOperation *)mappingOperation deleteExistingValueOfRelationshipWithMapping:(RKRelationshipMapping *)relationshipMapping error:(NSError **)error
{
// Validate the assignment policy
if (! relationshipMapping.assignmentPolicy == RKReplaceAssignmentPolicy) {
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: @"Unable to satisfy deletion request: Relationship mapping was expected to have an assignment policy of `RKReplaceAssignmentPolicy`, but did not." };
NSError *localError = [NSError errorWithDomain:RKErrorDomain code:RKMappingErrorInvalidAssignmentPolicy userInfo:userInfo];
if (error) *error = localError;
return NO;
}

// Delete any managed objects at the destination key path from the context
id existingValue = [mappingOperation.destinationObject valueForKeyPath:relationshipMapping.destinationKeyPath];
if ([existingValue isKindOfClass:[NSManagedObject class]]) {
[self.managedObjectContext deleteObject:existingValue];
} else {
if (RKObjectIsCollection(existingValue)) {
for (NSManagedObject *managedObject in existingValue) {
if (! [managedObject isKindOfClass:[NSManagedObject class]]) continue;
[self.managedObjectContext deleteObject:managedObject];
}
}
}

return YES;
}

@end
Loading

0 comments on commit 9103b9b

Please sign in to comment.