mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-23 20:31:13 +08:00
Major overhaul to the Core Data managed object identification and relationship connection support.
* Replaces primary key with `RKEntityIdentifier` * Add support for use of compound keys for object identification * Refactor `RKConnectionMapping` to `RKConnectionDescription` and add support for connecting with multiple attributes * Clarify naming of representation key methods to better match naming conventions * Add type transformation support for object identification * Greatly expand test coverage for object identification * Drop the `NSEntityDescription` category * Simplify the `RKManagedObjectCaching` protocol * Add compound key support to the Fetch Request and In Memory Cache implementations * Replace Kiwi with Specta for tests where contexts are helpful for organization * Rename `defaultValueForMissingAttribute` to `defaultValueForAttribute`
This commit is contained in:
@@ -31,4 +31,3 @@
|
||||
#import "RKPropertyInspector+CoreData.h"
|
||||
#import "NSManagedObjectContext+RKAdditions.h"
|
||||
#import "NSManagedObject+RKAdditions.h"
|
||||
#import "NSEntityDescription+RKAdditions.h"
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#import "NSManagedObjectContext+RKAdditions.h"
|
||||
#import "RKLog.h"
|
||||
#import "RKManagedObjectStore.h"
|
||||
#import "NSEntityDescription+RKAdditions.h"
|
||||
|
||||
@implementation NSManagedObject (RKAdditions)
|
||||
|
||||
|
||||
@@ -64,27 +64,27 @@
|
||||
*/
|
||||
- (NSUInteger)countForEntityForName:(NSString *)entityName predicate:(NSPredicate *)predicate error:(NSError **)error;
|
||||
|
||||
///----------------------------------------------
|
||||
/// @name Fetching Managed Objects by Primary Key
|
||||
///----------------------------------------------
|
||||
|
||||
/**
|
||||
Fetches a single managed object for the given entity with the given value for the primary key attribute in the receiver.
|
||||
|
||||
@param entity The entity of the managed object to be retrieved by primary key.
|
||||
@param primaryKeyValue The value for the entity's primary key attribute.
|
||||
@return The managed object with the primary key attribute equal to the given value or nil if none was found.
|
||||
*/
|
||||
- (id)fetchObjectForEntity:(NSEntityDescription *)entity withValueForPrimaryKeyAttribute:(id)primaryKeyValue;
|
||||
|
||||
/**
|
||||
Fetches a single managed object for the entity for the given name with the given value for the primary key attribute in the receiver.
|
||||
|
||||
@param entityName The name of the entity of the managed object to be retrieved by primary key.
|
||||
@param primaryKeyValue The value for the receiving entity's primary key attribute.
|
||||
@return The managed object with the primary key attribute equal to the given value or nil if none was found.
|
||||
*/
|
||||
- (id)fetchObjectForEntityForName:(NSString *)entityName withValueForPrimaryKeyAttribute:(id)primaryKeyValue;
|
||||
/////----------------------------------------------
|
||||
///// @name Fetching Managed Objects by Primary Key
|
||||
/////----------------------------------------------
|
||||
//
|
||||
///**
|
||||
// Fetches a single managed object for the given entity with the given value for the primary key attribute in the receiver.
|
||||
//
|
||||
// @param entity The entity of the managed object to be retrieved by primary key.
|
||||
// @param primaryKeyValue The value for the entity's primary key attribute.
|
||||
// @return The managed object with the primary key attribute equal to the given value or nil if none was found.
|
||||
// */
|
||||
//- (id)fetchObjectForEntity:(NSEntityDescription *)entity withValueForPrimaryKeyAttribute:(id)primaryKeyValue;
|
||||
//
|
||||
///**
|
||||
// Fetches a single managed object for the entity for the given name with the given value for the primary key attribute in the receiver.
|
||||
//
|
||||
// @param entityName The name of the entity of the managed object to be retrieved by primary key.
|
||||
// @param primaryKeyValue The value for the receiving entity's primary key attribute.
|
||||
// @return The managed object with the primary key attribute equal to the given value or nil if none was found.
|
||||
// */
|
||||
//- (id)fetchObjectForEntityForName:(NSString *)entityName withValueForPrimaryKeyAttribute:(id)primaryKeyValue;
|
||||
|
||||
///-------------------------------------------------
|
||||
/// @name Saving the Context to the Persistent Store
|
||||
|
||||
@@ -37,40 +37,40 @@
|
||||
return [self countForFetchRequest:fetchRequest error:error];
|
||||
}
|
||||
|
||||
- (id)fetchObjectForEntity:(NSEntityDescription *)entity withValueForPrimaryKeyAttribute:(id)primaryKeyValue
|
||||
{
|
||||
NSPredicate *predicate = [entity predicateForPrimaryKeyAttributeWithValue:primaryKeyValue];
|
||||
if (! predicate) {
|
||||
RKLogWarning(@"Attempt to fetchObjectForEntity for entity with nil primaryKeyAttribute. Set the primaryKeyAttributeName and try again! %@", self);
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest new];
|
||||
fetchRequest.entity = entity;
|
||||
fetchRequest.predicate = predicate;
|
||||
fetchRequest.fetchLimit = 1;
|
||||
__block NSError *error;
|
||||
__block NSArray *objects;
|
||||
[self performBlockAndWait:^{
|
||||
objects = [self executeFetchRequest:fetchRequest error:&error];
|
||||
}];
|
||||
if (! objects) {
|
||||
RKLogCoreDataError(error);
|
||||
return nil;
|
||||
}
|
||||
|
||||
if ([objects count] == 1) {
|
||||
return [objects objectAtIndex:0];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (id)fetchObjectForEntityForName:(NSString *)entityName withValueForPrimaryKeyAttribute:(id)primaryKeyValue
|
||||
{
|
||||
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:self];
|
||||
return [self fetchObjectForEntity:entity withValueForPrimaryKeyAttribute:primaryKeyValue];
|
||||
}
|
||||
//- (id)fetchObjectForEntity:(NSEntityDescription *)entity withValueForPrimaryKeyAttribute:(id)primaryKeyValue
|
||||
//{
|
||||
// NSPredicate *predicate = [entity predicateForPrimaryKeyAttributeWithValue:primaryKeyValue];
|
||||
// if (! predicate) {
|
||||
// RKLogWarning(@"Attempt to fetchObjectForEntity for entity with nil primaryKeyAttribute. Set the primaryKeyAttributeName and try again! %@", self);
|
||||
// return nil;
|
||||
// }
|
||||
//
|
||||
// NSFetchRequest *fetchRequest = [NSFetchRequest new];
|
||||
// fetchRequest.entity = entity;
|
||||
// fetchRequest.predicate = predicate;
|
||||
// fetchRequest.fetchLimit = 1;
|
||||
// __block NSError *error;
|
||||
// __block NSArray *objects;
|
||||
// [self performBlockAndWait:^{
|
||||
// objects = [self executeFetchRequest:fetchRequest error:&error];
|
||||
// }];
|
||||
// if (! objects) {
|
||||
// RKLogCoreDataError(error);
|
||||
// return nil;
|
||||
// }
|
||||
//
|
||||
// if ([objects count] == 1) {
|
||||
// return [objects objectAtIndex:0];
|
||||
// }
|
||||
//
|
||||
// return nil;
|
||||
//}
|
||||
//
|
||||
//- (id)fetchObjectForEntityForName:(NSString *)entityName withValueForPrimaryKeyAttribute:(id)primaryKeyValue
|
||||
//{
|
||||
// NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:self];
|
||||
// return [self fetchObjectForEntity:entity withValueForPrimaryKeyAttribute:primaryKeyValue];
|
||||
//}
|
||||
|
||||
- (BOOL)saveToPersistentStore:(NSError **)error
|
||||
{
|
||||
|
||||
26
Code/CoreData/RKConnectionDescription.h
Normal file
26
Code/CoreData/RKConnectionDescription.h
Normal file
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// RKConnectionDescription.h
|
||||
// RestKit
|
||||
//
|
||||
// Created by Blake Watters on 11/20/12.
|
||||
// Copyright (c) 2012 RestKit. All rights reserved.
|
||||
//
|
||||
|
||||
#import <CoreData/CoreData.h>
|
||||
|
||||
/**
|
||||
*/
|
||||
@interface RKConnectionDescription : NSObject <NSCopying>
|
||||
|
||||
@property (nonatomic, strong, readonly) NSRelationshipDescription *relationship;
|
||||
|
||||
- (id)initWithRelationship:(NSRelationshipDescription *)relationship attributes:(NSDictionary *)sourceToDestinationEntityAttributes;
|
||||
- (id)initWithRelationship:(NSRelationshipDescription *)relationship keyPath:(NSString *)keyPath;
|
||||
|
||||
@property (nonatomic, copy, readonly) NSDictionary *attributes; // nil unless foreign key
|
||||
- (BOOL)isForeignKeyConnection;
|
||||
|
||||
@property (nonatomic, copy, readonly) NSString *keyPath; // nil unless keyPath description
|
||||
- (BOOL)isKeyPathConnection;
|
||||
|
||||
@end
|
||||
129
Code/CoreData/RKConnectionDescription.m
Normal file
129
Code/CoreData/RKConnectionDescription.m
Normal file
@@ -0,0 +1,129 @@
|
||||
//
|
||||
// RKConnectionDescription.m
|
||||
// RestKit
|
||||
//
|
||||
// Created by Blake Watters on 11/20/12.
|
||||
// Copyright (c) 2012 RestKit. All rights reserved.
|
||||
//
|
||||
|
||||
#import "RKConnectionDescription.h"
|
||||
|
||||
static NSSet *RKSetWithInvalidAttributesForEntity(NSArray *attributes, NSEntityDescription *entity)
|
||||
{
|
||||
NSMutableSet *attributesSet = [NSMutableSet setWithArray:attributes];
|
||||
NSSet *validAttributeNames = [NSSet setWithArray:[[entity attributesByName] allKeys]];
|
||||
[attributesSet minusSet:validAttributeNames];
|
||||
return attributesSet;
|
||||
}
|
||||
|
||||
// Provides support for connecting a relationship by
|
||||
@interface RKForeignKeyConnectionDescription : RKConnectionDescription
|
||||
@end
|
||||
|
||||
// Provides support for connecting a relationship by traversing the object graph
|
||||
@interface RKKeyPathConnectionDescription : RKConnectionDescription
|
||||
@end
|
||||
|
||||
@interface RKConnectionDescription ()
|
||||
@property (nonatomic, strong, readwrite) NSRelationshipDescription *relationship;
|
||||
@property (nonatomic, copy, readwrite) NSDictionary *attributes;
|
||||
@property (nonatomic, copy, readwrite) NSString *keyPath;
|
||||
@end
|
||||
|
||||
@implementation RKConnectionDescription
|
||||
|
||||
- (id)initWithRelationship:(NSRelationshipDescription *)relationship attributes:(NSDictionary *)attributes
|
||||
{
|
||||
NSParameterAssert(relationship);
|
||||
NSParameterAssert(attributes);
|
||||
NSAssert([attributes count], @"Cannot connect a relationship without at least one pair of attributes describing the connection");
|
||||
NSSet *invalidSourceAttributes = RKSetWithInvalidAttributesForEntity([attributes allKeys], [relationship entity]);
|
||||
NSAssert([invalidSourceAttributes count] == 0, @"Cannot connect relationship: invalid attributes given for source entity '%@': %@", [[relationship entity] name], [[invalidSourceAttributes allObjects] componentsJoinedByString:@", "]);
|
||||
NSSet *invalidDestinationAttributes = RKSetWithInvalidAttributesForEntity([attributes allValues], [relationship destinationEntity]);
|
||||
NSAssert([invalidDestinationAttributes count] == 0, @"Cannot connect relationship: invalid attributes given for destination entity '%@': %@", [[relationship destinationEntity] name], [[invalidDestinationAttributes allObjects] componentsJoinedByString:@", "]);
|
||||
|
||||
self = [[RKForeignKeyConnectionDescription alloc] init];
|
||||
if (self) {
|
||||
self.relationship = relationship;
|
||||
self.attributes = attributes;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithRelationship:(NSRelationshipDescription *)relationship keyPath:(NSString *)keyPath
|
||||
{
|
||||
NSParameterAssert(relationship);
|
||||
NSParameterAssert(keyPath);
|
||||
self = [[RKKeyPathConnectionDescription alloc] init];
|
||||
if (self) {
|
||||
self.relationship = relationship;
|
||||
self.keyPath = keyPath;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (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.",
|
||||
NSStringFromClass([self class])]
|
||||
userInfo:nil];
|
||||
}
|
||||
return [super init];
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone
|
||||
{
|
||||
if ([self isForeignKeyConnection]) {
|
||||
return [[[self class] allocWithZone:zone] initWithRelationship:self.relationship attributes:self.attributes];
|
||||
} else if ([self isKeyPathConnection]) {
|
||||
return [[[self class] allocWithZone:zone] initWithRelationship:self.relationship keyPath:self.keyPath];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL)isForeignKeyConnection
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)isKeyPathConnection
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RKForeignKeyConnectionDescription
|
||||
|
||||
- (BOOL)isForeignKeyConnection
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"<%@:%p connecting Relationship '%@' from Entity '%@' to Destination Entity '%@' with attributes=%@>",
|
||||
NSStringFromClass([self class]), self, [self.relationship name], [[self.relationship entity] name],
|
||||
[[self.relationship destinationEntity] name], self.attributes];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RKKeyPathConnectionDescription
|
||||
|
||||
- (BOOL)isKeyPathConnection
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"<%@:%p connecting Relationship '%@' of Entity '%@' with keyPath=%@>",
|
||||
NSStringFromClass([self class]), self, [self.relationship name], [[self.relationship entity] name], self.keyPath];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class RKConnectionMapping;
|
||||
@class RKConnectionDescription;
|
||||
@protocol RKManagedObjectCaching;
|
||||
|
||||
/**
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
@see `RKConnectionMapping`
|
||||
*/
|
||||
@interface RKRelationshipConnectionOperation : NSOperation
|
||||
@interface RKConnectionOperation : NSOperation
|
||||
|
||||
///-------------------------------------------------------
|
||||
/// @name Initializing a Relationship Connection Operation
|
||||
@@ -45,7 +45,7 @@
|
||||
@return The receiver, initialized with the given managed object, connection mapping, and managed object cache.
|
||||
*/
|
||||
- (id)initWithManagedObject:(NSManagedObject *)managedObject
|
||||
connectionMapping:(RKConnectionMapping *)connectionMapping
|
||||
connection:(RKConnectionDescription *)connection
|
||||
managedObjectCache:(id<RKManagedObjectCaching>)managedObjectCache;
|
||||
|
||||
///--------------------------------------------
|
||||
@@ -60,7 +60,7 @@
|
||||
/**
|
||||
The connection mapping describing the relationship connection the receiver will attempt to connect.
|
||||
*/
|
||||
@property (nonatomic, strong, readonly) RKConnectionMapping *connectionMapping;
|
||||
@property (nonatomic, strong, readonly) RKConnectionDescription *connection;
|
||||
|
||||
/**
|
||||
The managed object cache the receiver will use to fetch a related object satisfying the connection mapping.
|
||||
@@ -19,7 +19,8 @@
|
||||
//
|
||||
|
||||
#import <CoreData/CoreData.h>
|
||||
#import "RKRelationshipConnectionOperation.h"
|
||||
#import "RKConnectionOperation.h"
|
||||
#import "RKConnectionDescription.h"
|
||||
#import "RKEntityMapping.h"
|
||||
#import "RKLog.h"
|
||||
#import "RKManagedObjectCaching.h"
|
||||
@@ -37,9 +38,21 @@ static id RKMutableSetValueForRelationship(NSRelationshipDescription *relationsh
|
||||
return [relationship isOrdered] ? [NSMutableOrderedSet orderedSet] : [NSMutableSet set];
|
||||
}
|
||||
|
||||
@interface RKRelationshipConnectionOperation ()
|
||||
static NSDictionary *RKConnectionAttributeValuesWithObject(RKConnectionDescription *connection, NSManagedObject *managedObject)
|
||||
{
|
||||
NSCAssert([connection isForeignKeyConnection], @"Only valid for a foreign key connection");
|
||||
NSMutableDictionary *destinationEntityAttributeValues = [NSMutableDictionary dictionaryWithCapacity:[connection.attributes count]];
|
||||
for (NSString *sourceAttribute in connection.attributes) {
|
||||
NSString *destinationAttribute = connection.attributes[sourceAttribute];
|
||||
id sourceValue = [managedObject valueForKey:sourceAttribute];
|
||||
[destinationEntityAttributeValues setValue:sourceValue forKey:destinationAttribute];
|
||||
}
|
||||
return destinationEntityAttributeValues;
|
||||
}
|
||||
|
||||
@interface RKConnectionOperation ()
|
||||
@property (nonatomic, strong, readwrite) NSManagedObject *managedObject;
|
||||
@property (nonatomic, strong, readwrite) RKConnectionMapping *connectionMapping;
|
||||
@property (nonatomic, strong, readwrite) RKConnectionDescription *connection;
|
||||
@property (nonatomic, strong, readwrite) id<RKManagedObjectCaching> managedObjectCache;
|
||||
@property (nonatomic, strong, readwrite) NSError *error;
|
||||
@property (nonatomic, strong, readwrite) id connectedValue;
|
||||
@@ -49,19 +62,20 @@ static id RKMutableSetValueForRelationship(NSRelationshipDescription *relationsh
|
||||
|
||||
@end
|
||||
|
||||
@implementation RKRelationshipConnectionOperation
|
||||
@implementation RKConnectionOperation
|
||||
|
||||
|
||||
- (id)initWithManagedObject:(NSManagedObject *)managedObject connectionMapping:(RKConnectionMapping *)connectionMapping managedObjectCache:(id<RKManagedObjectCaching>)managedObjectCache
|
||||
- (id)initWithManagedObject:(NSManagedObject *)managedObject
|
||||
connection:(RKConnectionDescription *)connection
|
||||
managedObjectCache:(id<RKManagedObjectCaching>)managedObjectCache;
|
||||
{
|
||||
NSParameterAssert(managedObject);
|
||||
NSAssert([managedObject isKindOfClass:[NSManagedObject class]], @"Relationship connection requires an instance of NSManagedObject");
|
||||
NSParameterAssert(connectionMapping);
|
||||
NSParameterAssert(connection);
|
||||
NSParameterAssert(managedObjectCache);
|
||||
self = [self init];
|
||||
if (self) {
|
||||
self.managedObject = managedObject;
|
||||
self.connectionMapping = connectionMapping;
|
||||
self.connection = connection;
|
||||
self.managedObjectCache = managedObjectCache;
|
||||
}
|
||||
|
||||
@@ -73,23 +87,14 @@ static id RKMutableSetValueForRelationship(NSRelationshipDescription *relationsh
|
||||
return self.managedObject.managedObjectContext;
|
||||
}
|
||||
|
||||
- (NSManagedObject *)findOneConnectedWithSourceValue:(id)sourceValue
|
||||
{
|
||||
NSAssert(self.managedObjectContext, @"Cannot lookup objects with a nil managedObjectContext");
|
||||
return [self.managedObjectCache findInstanceOfEntity:self.connectionMapping.relationship.destinationEntity
|
||||
withPrimaryKeyAttribute:self.connectionMapping.destinationKeyPath
|
||||
value:sourceValue
|
||||
inManagedObjectContext:self.managedObjectContext];
|
||||
}
|
||||
|
||||
- (id)relationshipValueWithConnectionResult:(id)result
|
||||
{
|
||||
// TODO: Replace with use of object mapping engine for type conversion
|
||||
|
||||
// NOTE: This is a nasty hack to work around the fact that NSOrderedSet does not support key-value
|
||||
// collection operators. We try to detect and unpack a doubly wrapped collection
|
||||
if ([self.connectionMapping.relationship isToMany] && RKObjectIsCollectionOfCollections(result)) {
|
||||
id mutableSet = RKMutableSetValueForRelationship(self.connectionMapping.relationship);
|
||||
if ([self.connection.relationship isToMany] && RKObjectIsCollectionOfCollections(result)) {
|
||||
id mutableSet = RKMutableSetValueForRelationship(self.connection.relationship);
|
||||
for (id<NSFastEnumeration> enumerable in result) {
|
||||
for (id object in enumerable) {
|
||||
[mutableSet addObject:object];
|
||||
@@ -99,27 +104,27 @@ static id RKMutableSetValueForRelationship(NSRelationshipDescription *relationsh
|
||||
return mutableSet;
|
||||
}
|
||||
|
||||
if ([self.connectionMapping.relationship isToMany]) {
|
||||
if ([self.connection.relationship isToMany]) {
|
||||
if ([result isKindOfClass:[NSArray class]]) {
|
||||
if ([self.connectionMapping.relationship isOrdered]) {
|
||||
if ([self.connection.relationship isOrdered]) {
|
||||
return [NSOrderedSet orderedSetWithArray:result];
|
||||
} else {
|
||||
return [NSSet setWithArray:result];
|
||||
}
|
||||
} else if ([result isKindOfClass:[NSSet class]]) {
|
||||
if ([self.connectionMapping.relationship isOrdered]) {
|
||||
if ([self.connection.relationship isOrdered]) {
|
||||
return [NSOrderedSet orderedSetWithSet:result];
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
} else if ([result isKindOfClass:[NSOrderedSet class]]) {
|
||||
if ([self.connectionMapping.relationship isOrdered]) {
|
||||
if ([self.connection.relationship isOrdered]) {
|
||||
return result;
|
||||
} else {
|
||||
return [(NSOrderedSet *)result set];
|
||||
}
|
||||
} else {
|
||||
if ([self.connectionMapping.relationship isOrdered]) {
|
||||
if ([self.connection.relationship isOrdered]) {
|
||||
return [NSOrderedSet orderedSetWithObject:result];
|
||||
} else {
|
||||
return [NSSet setWithObject:result];
|
||||
@@ -143,61 +148,56 @@ static id RKMutableSetValueForRelationship(NSRelationshipDescription *relationsh
|
||||
|
||||
for (id value in values) {
|
||||
NSAssert(self.managedObjectContext, @"Cannot lookup objects with a nil managedObjectContext");
|
||||
NSArray *objects = [self.managedObjectCache findInstancesOfEntity:self.connectionMapping.relationship.destinationEntity
|
||||
withPrimaryKeyAttribute:self.connectionMapping.destinationKeyPath
|
||||
value:value
|
||||
inManagedObjectContext:self.managedObjectContext];
|
||||
[result addObjectsFromArray:objects];
|
||||
// NSArray *objects = [self.managedObjectCache findInstancesOfEntity:self.connectionMapping.relationship.destinationEntity
|
||||
// withPrimaryKeyAttribute:self.connectionMapping.destinationKeyPath
|
||||
// value:value
|
||||
// inManagedObjectContext:self.managedObjectContext];
|
||||
// [result addObjectsFromArray:objects];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
- (BOOL)isToMany
|
||||
{
|
||||
return self.connectionMapping.relationship.isToMany;
|
||||
}
|
||||
|
||||
- (BOOL)checkMatcher
|
||||
{
|
||||
if (!self.connectionMapping.matcher) {
|
||||
return YES;
|
||||
} else {
|
||||
return [self.connectionMapping.matcher matches:self.managedObject];
|
||||
}
|
||||
}
|
||||
//- (NSManagedObject *)findOneConnectedWithSourceValue:(id)sourceValue
|
||||
//{
|
||||
// NSAssert(self.managedObjectContext, @"Cannot lookup objects with a nil managedObjectContext");
|
||||
// NSArray *
|
||||
// return [self.managedObjectCache findInstanceOfEntity:self.connectionMapping.relationship.destinationEntity
|
||||
// withPrimaryKeyAttribute:self.connectionMapping.destinationKeyPath
|
||||
// value:sourceValue
|
||||
// inManagedObjectContext:self.managedObjectContext];
|
||||
//}
|
||||
|
||||
- (id)findConnected
|
||||
{
|
||||
if ([self checkMatcher]) {
|
||||
id connectionResult = nil;
|
||||
if ([self.connectionMapping isForeignKeyConnection]) {
|
||||
BOOL isToMany = [self isToMany];
|
||||
id sourceValue = [self.managedObject valueForKey:self.connectionMapping.sourceKeyPath];
|
||||
if (isToMany) {
|
||||
connectionResult = [self findAllConnectedWithSourceValue:sourceValue];
|
||||
} else {
|
||||
connectionResult = [self findOneConnectedWithSourceValue:sourceValue];
|
||||
}
|
||||
} else if ([self.connectionMapping isKeyPathConnection]) {
|
||||
connectionResult = [self.managedObject valueForKeyPath:self.connectionMapping.sourceKeyPath];
|
||||
id connectionResult = nil;
|
||||
if ([self.connection isForeignKeyConnection]) {
|
||||
NSDictionary *attributeValues = RKConnectionAttributeValuesWithObject(self.connection, self.managedObject);
|
||||
NSArray *managedObjects = [self.managedObjectCache managedObjectsWithEntity:[self.connection.relationship destinationEntity]
|
||||
attributeValues:attributeValues
|
||||
inManagedObjectContext:self.managedObjectContext];
|
||||
if ([self.connection.relationship isToMany]) {
|
||||
connectionResult = managedObjects;
|
||||
} else {
|
||||
@throw [NSException exceptionWithName:NSInternalInconsistencyException
|
||||
reason:[NSString stringWithFormat:@"%@ Attempted to establish a relationship using a mapping"
|
||||
"specifies neither a foreign key or a key path connection: %@",
|
||||
NSStringFromClass([self class]), self.connectionMapping]
|
||||
userInfo:nil];
|
||||
if ([managedObjects count] > 1) RKLogWarning(@"Retrieved %d objects satisfying connection criteria for one-to-one relationship connection: only the first result will be connected.", [managedObjects count]);
|
||||
connectionResult = managedObjects[0];
|
||||
}
|
||||
|
||||
return [self relationshipValueWithConnectionResult:connectionResult];
|
||||
} else if ([self.connection isKeyPathConnection]) {
|
||||
connectionResult = [self.managedObject valueForKeyPath:self.connection.keyPath];
|
||||
} else {
|
||||
return nil;
|
||||
@throw [NSException exceptionWithName:NSInternalInconsistencyException
|
||||
reason:[NSString stringWithFormat:@"%@ Attempted to establish a relationship using a mapping that"
|
||||
" specifies neither a foreign key or a key path connection: %@",
|
||||
NSStringFromClass([self class]), self.connection]
|
||||
userInfo:nil];
|
||||
}
|
||||
|
||||
return [self relationshipValueWithConnectionResult:connectionResult];
|
||||
}
|
||||
|
||||
- (void)connectRelationship
|
||||
{
|
||||
NSString *relationshipName = self.connectionMapping.relationship.name;
|
||||
RKLogTrace(@"Connecting relationship '%@' with mapping: %@", relationshipName, self.connectionMapping);
|
||||
NSString *relationshipName = self.connection.relationship.name;
|
||||
RKLogTrace(@"Connecting relationship '%@' with mapping: %@", relationshipName, self.connection);
|
||||
[self.managedObjectContext performBlockAndWait:^{
|
||||
self.connectedValue = [self findConnected];
|
||||
[self.managedObject setValue:self.connectedValue forKeyPath:relationshipName];
|
||||
@@ -214,7 +214,7 @@ static id RKMutableSetValueForRelationship(NSRelationshipDescription *relationsh
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"<%@:%p %@ in %@ using %@>",
|
||||
[self class], self, self.connectionMapping, self.managedObjectContext, self.managedObjectCache];
|
||||
[self class], self, self.connection, self.managedObjectContext, self.managedObjectCache];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -41,12 +41,12 @@
|
||||
Initializes the receiver with a given entity, attribute, and managed object context.
|
||||
|
||||
@param entity The Core Data entity description for the managed objects being cached.
|
||||
@param attributeName The name of an attribute within the cached entity that acts as the cache key.
|
||||
@param attributeNames An array of attribute names used as the cache keys.
|
||||
@param context The managed object context the cache retrieves the cached objects from.
|
||||
@return The receiver, initialized with the given entity, attribute, and managed object
|
||||
context.
|
||||
*/
|
||||
- (id)initWithEntity:(NSEntityDescription *)entity attribute:(NSString *)attributeName managedObjectContext:(NSManagedObjectContext *)context;
|
||||
- (id)initWithEntity:(NSEntityDescription *)entity attributes:(NSArray *)attributeNames managedObjectContext:(NSManagedObjectContext *)context;
|
||||
|
||||
///-----------------------------
|
||||
/// @name Getting Cache Identity
|
||||
@@ -58,9 +58,9 @@
|
||||
@property (nonatomic, readonly) NSEntityDescription *entity;
|
||||
|
||||
/**
|
||||
An attribute that is part of the cached entity that acts as the cache key.
|
||||
An array of attribute names specifying attributes of the cached entity that act as the cache key.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSString *attribute;
|
||||
@property (nonatomic, readonly) NSArray *attributes;
|
||||
|
||||
/**
|
||||
The managed object context the receiver fetches cached objects from.
|
||||
@@ -105,14 +105,12 @@
|
||||
- (NSUInteger)count;
|
||||
|
||||
/**
|
||||
Returns the total number of cached objects with a given value for the attribute acting as the cache key.
|
||||
Returns the total number of cached objects whose attributes match the values in the given dictionary of attribute values.
|
||||
|
||||
@param attributeValue The value for the cache key attribute to retrieve
|
||||
a count of the objects with a matching value.
|
||||
@return The number of objects in the cache with the given value for the cache
|
||||
attribute of the receiver.
|
||||
@param attributeValues The value for the cache key attribute to retrieve a count of the objects with a matching value.
|
||||
@return The number of objects in the cache with the given value for the cache attribute of the receiver.
|
||||
*/
|
||||
- (NSUInteger)countWithAttributeValue:(id)attributeValue;
|
||||
- (NSUInteger)countWithAttributeValues:(NSDictionary *)attributeValues;
|
||||
|
||||
/**
|
||||
Returns the number of unique attribute values contained within the receiver.
|
||||
@@ -137,17 +135,16 @@
|
||||
@param attributeValue The value with which to check the cache for objects with a matching value.
|
||||
@return YES if one or more objects with the given value for the cache key attribute is present in the cache, otherwise NO.
|
||||
*/
|
||||
- (BOOL)containsObjectWithAttributeValue:(id)attributeValue;
|
||||
- (BOOL)containsObjectWithAttributeValues:(NSDictionary *)attributeValues;
|
||||
|
||||
/**
|
||||
Returns the first object with a matching value for the cache key attribute
|
||||
in a given managed object context.
|
||||
Returns the first object with a matching value for the cache key attributes in a given managed object context.
|
||||
|
||||
@param attributeValue A value for the cache key attribute.
|
||||
@param attributeValues A value for the cache key attribute.
|
||||
@param context The managed object context to retrieve the object from.
|
||||
@return An object with the value of attribute matching attributeValue or nil.
|
||||
*/
|
||||
- (NSManagedObject *)objectWithAttributeValue:(id)attributeValue inContext:(NSManagedObjectContext *)context;
|
||||
- (NSManagedObject *)objectWithAttributeValues:(NSDictionary *)attributeValues inContext:(NSManagedObjectContext *)context;
|
||||
|
||||
/**
|
||||
Returns the collection of objects with a matching value for the cache key attribute in a given managed object context.
|
||||
@@ -156,7 +153,7 @@
|
||||
@param context The managed object context to retrieve the objects from.
|
||||
@return An array of objects with the value of attribute matching attributeValue or an empty array.
|
||||
*/
|
||||
- (NSArray *)objectsWithAttributeValue:(id)attributeValue inContext:(NSManagedObjectContext *)context;
|
||||
- (NSArray *)objectsWithAttributeValues:(NSDictionary *)attributeValues inContext:(NSManagedObjectContext *)context;
|
||||
|
||||
///------------------------------
|
||||
/// @name Managing Cached Objects
|
||||
|
||||
@@ -32,23 +32,44 @@
|
||||
#undef RKLogComponent
|
||||
#define RKLogComponent RKlcl_cRestKitCoreDataCache
|
||||
|
||||
static id RKCacheKeyValueForEntityAttributeWithValue(NSEntityDescription *entity, NSString *attribute, id value)
|
||||
{
|
||||
if ([value isKindOfClass:[NSString class]] || [value isEqual:[NSNull null]]) {
|
||||
return value;
|
||||
}
|
||||
|
||||
Class attributeType = [[RKPropertyInspector sharedInspector] classForPropertyNamed:attribute ofEntity:entity];
|
||||
return [attributeType instancesRespondToSelector:@selector(stringValue)] ? [value stringValue] : value;
|
||||
}
|
||||
|
||||
static NSString *RKCacheKeyForEntityWithAttributeValues(NSEntityDescription *entity, NSDictionary *attributeValues)
|
||||
{
|
||||
NSArray *sortedAttributes = [[attributeValues allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
|
||||
NSMutableArray *sortedValues = [NSMutableArray arrayWithCapacity:[sortedAttributes count]];
|
||||
[sortedAttributes enumerateObjectsUsingBlock:^(NSString *attributeName, NSUInteger idx, BOOL *stop) {
|
||||
id cacheKeyValue = RKCacheKeyValueForEntityAttributeWithValue(entity, attributeName, attributeValues[attributeName]);
|
||||
[sortedValues addObject:cacheKeyValue];
|
||||
}];
|
||||
|
||||
return [sortedValues componentsJoinedByString:@":"];
|
||||
}
|
||||
|
||||
@interface RKEntityByAttributeCache ()
|
||||
@property (nonatomic, strong) NSMutableDictionary *attributeValuesToObjectIDs;
|
||||
@property (nonatomic, strong) NSMutableDictionary *cacheKeysToObjectIDs;
|
||||
@end
|
||||
|
||||
@implementation RKEntityByAttributeCache
|
||||
|
||||
|
||||
- (id)initWithEntity:(NSEntityDescription *)entity attribute:(NSString *)attributeName managedObjectContext:(NSManagedObjectContext *)context
|
||||
- (id)initWithEntity:(NSEntityDescription *)entity attributes:(NSArray *)attributeNames managedObjectContext:(NSManagedObjectContext *)context
|
||||
{
|
||||
NSParameterAssert(entity);
|
||||
NSParameterAssert(attributeName);
|
||||
NSParameterAssert(attributeNames);
|
||||
NSParameterAssert(context);
|
||||
|
||||
self = [self init];
|
||||
if (self) {
|
||||
_entity = entity;
|
||||
_attribute = attributeName;
|
||||
_attributes = attributeNames;
|
||||
_managedObjectContext = context;
|
||||
_monitorsContextForChanges = YES;
|
||||
|
||||
@@ -75,35 +96,25 @@
|
||||
|
||||
- (NSUInteger)count
|
||||
{
|
||||
return [[[self.attributeValuesToObjectIDs allValues] valueForKeyPath:@"@sum.@count"] integerValue];
|
||||
return [[[self.cacheKeysToObjectIDs allValues] valueForKeyPath:@"@sum.@count"] integerValue];
|
||||
}
|
||||
|
||||
- (NSUInteger)countOfAttributeValues
|
||||
{
|
||||
return [self.attributeValuesToObjectIDs count];
|
||||
return [self.cacheKeysToObjectIDs count];
|
||||
}
|
||||
|
||||
- (NSUInteger)countWithAttributeValue:(id)attributeValue
|
||||
- (NSUInteger)countWithAttributeValues:(NSDictionary *)attributeValues
|
||||
{
|
||||
return [[self objectsWithAttributeValue:attributeValue inContext:self.managedObjectContext] count];
|
||||
}
|
||||
|
||||
- (BOOL)shouldCoerceAttributeToString:(NSString *)attributeValue
|
||||
{
|
||||
if ([attributeValue isKindOfClass:[NSString class]] || [attributeValue isEqual:[NSNull null]]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
Class attributeType = [[RKPropertyInspector sharedInspector] classForPropertyNamed:self.attribute ofEntity:self.entity];
|
||||
return [attributeType instancesRespondToSelector:@selector(stringValue)];
|
||||
return [[self objectsWithAttributeValues:attributeValues inContext:self.managedObjectContext] count];
|
||||
}
|
||||
|
||||
- (void)load
|
||||
{
|
||||
RKLogDebug(@"Loading entity cache for Entity '%@' by attribute '%@' in managed object context %@ (concurrencyType = %ld)",
|
||||
self.entity.name, self.attribute, self.managedObjectContext, (unsigned long)self.managedObjectContext.concurrencyType);
|
||||
@synchronized(self.attributeValuesToObjectIDs) {
|
||||
self.attributeValuesToObjectIDs = [NSMutableDictionary dictionary];
|
||||
RKLogDebug(@"Loading entity cache for Entity '%@' by attributes '%@' in managed object context %@ (concurrencyType = %ld)",
|
||||
self.entity.name, self.attributes, self.managedObjectContext, (unsigned long)self.managedObjectContext.concurrencyType);
|
||||
@synchronized(self.cacheKeysToObjectIDs) {
|
||||
self.cacheKeysToObjectIDs = [NSMutableDictionary dictionary];
|
||||
|
||||
NSExpressionDescription* objectIDExpression = [NSExpressionDescription new];
|
||||
objectIDExpression.name = @"objectID";
|
||||
@@ -114,7 +125,7 @@
|
||||
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
|
||||
fetchRequest.entity = self.entity;
|
||||
fetchRequest.resultType = NSDictionaryResultType;
|
||||
fetchRequest.propertiesToFetch = [NSArray arrayWithObjects:objectIDExpression, self.attribute, nil];
|
||||
fetchRequest.propertiesToFetch = [self.attributes arrayByAddingObject:objectIDExpression];
|
||||
|
||||
[self.managedObjectContext performBlockAndWait:^{
|
||||
NSError *error = nil;
|
||||
@@ -127,9 +138,9 @@
|
||||
}
|
||||
|
||||
for (NSDictionary *dictionary in dictionaries) {
|
||||
id attributeValue = [dictionary objectForKey:self.attribute];
|
||||
NSManagedObjectID *objectID = [dictionary objectForKey:@"objectID"];
|
||||
[self setObjectID:objectID forAttributeValue:attributeValue];
|
||||
NSDictionary *attributeValues = [dictionary dictionaryWithValuesForKeys:self.attributes];
|
||||
[self setObjectID:objectID forAttributeValues:attributeValues];
|
||||
}
|
||||
}];
|
||||
}
|
||||
@@ -137,9 +148,9 @@
|
||||
|
||||
- (void)flush
|
||||
{
|
||||
@synchronized(self.attributeValuesToObjectIDs) {
|
||||
RKLogDebug(@"Flushing entity cache for Entity '%@' by attribute '%@'", self.entity.name, self.attribute);
|
||||
self.attributeValuesToObjectIDs = nil;
|
||||
@synchronized(self.cacheKeysToObjectIDs) {
|
||||
RKLogDebug(@"Flushing entity cache for Entity '%@' by attributes '%@'", self.entity.name, self.attributes);
|
||||
self.cacheKeysToObjectIDs = nil;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +162,7 @@
|
||||
|
||||
- (BOOL)isLoaded
|
||||
{
|
||||
return (self.attributeValuesToObjectIDs != nil);
|
||||
return (self.cacheKeysToObjectIDs != nil);
|
||||
}
|
||||
|
||||
- (NSManagedObject *)objectForObjectID:(NSManagedObjectID *)objectID inContext:(NSManagedObjectContext *)context
|
||||
@@ -180,18 +191,19 @@
|
||||
return object;
|
||||
}
|
||||
|
||||
- (NSManagedObject *)objectWithAttributeValue:(id)attributeValue inContext:(NSManagedObjectContext *)context
|
||||
- (NSManagedObject *)objectWithAttributeValues:(NSDictionary *)attributeValues inContext:(NSManagedObjectContext *)context
|
||||
{
|
||||
NSArray *objects = [self objectsWithAttributeValue:attributeValue inContext:context];
|
||||
NSArray *objects = [self objectsWithAttributeValues:attributeValues inContext:context];
|
||||
return ([objects count] > 0) ? [objects objectAtIndex:0] : nil;
|
||||
}
|
||||
|
||||
- (NSArray *)objectsWithAttributeValue:(id)attributeValue inContext:(NSManagedObjectContext *)context
|
||||
- (NSArray *)objectsWithAttributeValues:(NSDictionary *)attributeValues inContext:(NSManagedObjectContext *)context
|
||||
{
|
||||
attributeValue = [self shouldCoerceAttributeToString:attributeValue] ? [attributeValue stringValue] : attributeValue;
|
||||
// TODO: Assert that the attribute values contains all of the cache attributes!!!
|
||||
NSString *cacheKey = RKCacheKeyForEntityWithAttributeValues(self.entity, attributeValues);
|
||||
NSArray *objectIDs = nil;
|
||||
@synchronized(self.attributeValuesToObjectIDs) {
|
||||
objectIDs = [[NSArray alloc] initWithArray:[self.attributeValuesToObjectIDs objectForKey:attributeValue] copyItems:YES];
|
||||
@synchronized(self.cacheKeysToObjectIDs) {
|
||||
objectIDs = [[NSArray alloc] initWithArray:[self.cacheKeysToObjectIDs objectForKey:cacheKey] copyItems:YES];
|
||||
}
|
||||
if ([objectIDs count]) {
|
||||
/**
|
||||
@@ -205,8 +217,8 @@
|
||||
if (object) {
|
||||
[objects addObject:object];
|
||||
} else {
|
||||
RKLogDebug(@"Evicting objectID association for attribute '%@'=>'%@' of Entity '%@': %@", self.attribute, attributeValue, self.entity.name, objectID);
|
||||
[self removeObjectID:objectID forAttributeValue:attributeValue];
|
||||
RKLogDebug(@"Evicting objectID association for attributes %@ of Entity '%@': %@", attributeValues, self.entity.name, objectID);
|
||||
[self removeObjectID:objectID forAttributeValues:attributeValues];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,12 +228,12 @@
|
||||
return [NSArray array];
|
||||
}
|
||||
|
||||
- (void)setObjectID:(NSManagedObjectID *)objectID forAttributeValue:(id)attributeValue
|
||||
- (void)setObjectID:(NSManagedObjectID *)objectID forAttributeValues:(NSDictionary *)attributeValues
|
||||
{
|
||||
@synchronized(self.attributeValuesToObjectIDs) {
|
||||
attributeValue = [self shouldCoerceAttributeToString:attributeValue] ? [attributeValue stringValue] : attributeValue;
|
||||
if (attributeValue) {
|
||||
NSMutableArray *objectIDs = [self.attributeValuesToObjectIDs objectForKey:attributeValue];
|
||||
@synchronized(self.cacheKeysToObjectIDs) {
|
||||
if (attributeValues && [attributeValues count]) {
|
||||
NSString *cacheKey = RKCacheKeyForEntityWithAttributeValues(self.entity, attributeValues);
|
||||
NSMutableArray *objectIDs = [self.cacheKeysToObjectIDs objectForKey:cacheKey];
|
||||
if (objectIDs) {
|
||||
if (! [objectIDs containsObject:objectID]) {
|
||||
[objectIDs addObject:objectID];
|
||||
@@ -230,27 +242,25 @@
|
||||
objectIDs = [NSMutableArray arrayWithObject:objectID];
|
||||
}
|
||||
|
||||
|
||||
if (nil == self.attributeValuesToObjectIDs) self.attributeValuesToObjectIDs = [NSMutableDictionary dictionary];
|
||||
[self.attributeValuesToObjectIDs setValue:objectIDs forKey:attributeValue];
|
||||
if (nil == self.cacheKeysToObjectIDs) self.cacheKeysToObjectIDs = [NSMutableDictionary dictionary];
|
||||
[self.cacheKeysToObjectIDs setValue:objectIDs forKey:cacheKey];
|
||||
} else {
|
||||
RKLogWarning(@"Unable to add object for object ID %@: nil value for attribute '%@'", objectID, self.attribute);
|
||||
RKLogWarning(@"Unable to add object for object ID %@: empty values dictionary for attributes '%@'", objectID, self.attributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)removeObjectID:(NSManagedObjectID *)objectID forAttributeValue:(id)attributeValue
|
||||
- (void)removeObjectID:(NSManagedObjectID *)objectID forAttributeValues:(NSDictionary *)attributeValues
|
||||
{
|
||||
@synchronized(self.attributeValuesToObjectIDs) {
|
||||
// Coerce to a string if possible
|
||||
attributeValue = [self shouldCoerceAttributeToString:attributeValue] ? [attributeValue stringValue] : attributeValue;
|
||||
if (attributeValue) {
|
||||
NSMutableArray *objectIDs = [self.attributeValuesToObjectIDs objectForKey:attributeValue];
|
||||
@synchronized(self.cacheKeysToObjectIDs) {
|
||||
if (attributeValues && [attributeValues count]) {
|
||||
NSString *cacheKey = RKCacheKeyForEntityWithAttributeValues(self.entity, attributeValues);
|
||||
NSMutableArray *objectIDs = [self.cacheKeysToObjectIDs objectForKey:cacheKey];
|
||||
if (objectIDs && [objectIDs containsObject:objectID]) {
|
||||
[objectIDs removeObject:objectID];
|
||||
}
|
||||
} else {
|
||||
RKLogWarning(@"Unable to remove object for object ID %@: nil value for attribute '%@'", objectID, self.attribute);
|
||||
RKLogWarning(@"Unable to remove object for object ID %@: empty values dictionary for attributes '%@'", objectID, self.attributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -258,42 +268,39 @@
|
||||
- (void)addObject:(NSManagedObject *)object
|
||||
{
|
||||
__block NSEntityDescription *entity;
|
||||
__block id attributeValue;
|
||||
__block NSDictionary *attributeValues;
|
||||
__block NSManagedObjectID *objectID;
|
||||
[self.managedObjectContext performBlockAndWait:^{
|
||||
entity = object.entity;
|
||||
objectID = [object objectID];
|
||||
attributeValue = [object valueForKey:self.attribute];
|
||||
attributeValues = [object dictionaryWithValuesForKeys:self.attributes];
|
||||
}];
|
||||
NSAssert([entity isKindOfEntity:self.entity], @"Cannot add object with entity '%@' to cache for entity of '%@'", [entity name], [self.entity name]);
|
||||
// Coerce to a string if possible
|
||||
[self setObjectID:objectID forAttributeValue:attributeValue];
|
||||
[self setObjectID:objectID forAttributeValues:attributeValues];
|
||||
}
|
||||
|
||||
- (void)removeObject:(NSManagedObject *)object
|
||||
{
|
||||
__block NSEntityDescription *entity;
|
||||
__block id attributeValue;
|
||||
__block NSDictionary *attributeValues;
|
||||
__block NSManagedObjectID *objectID;
|
||||
[object.managedObjectContext performBlockAndWait:^{
|
||||
entity = object.entity;
|
||||
objectID = [object objectID];
|
||||
attributeValue = [object valueForKey:self.attribute];
|
||||
attributeValues = [object dictionaryWithValuesForKeys:self.attributes];
|
||||
}];
|
||||
NSAssert([entity isKindOfEntity:self.entity], @"Cannot remove object with entity '%@' from cache for entity of '%@'", [entity name], [self.entity name]);
|
||||
[self removeObjectID:objectID forAttributeValue:attributeValue];
|
||||
[self removeObjectID:objectID forAttributeValues:attributeValues];
|
||||
}
|
||||
|
||||
- (BOOL)containsObjectWithAttributeValue:(id)attributeValue
|
||||
- (BOOL)containsObjectWithAttributeValues:(NSDictionary *)attributeValues
|
||||
{
|
||||
// Coerce to a string if possible
|
||||
attributeValue = [self shouldCoerceAttributeToString:attributeValue] ? [attributeValue stringValue] : attributeValue;
|
||||
return [[self objectsWithAttributeValue:attributeValue inContext:self.managedObjectContext] count] > 0;
|
||||
return [[self objectsWithAttributeValues:attributeValues inContext:self.managedObjectContext] count] > 0;
|
||||
}
|
||||
|
||||
- (BOOL)containsObject:(NSManagedObject *)object
|
||||
{
|
||||
NSArray *allObjectIDs = [[self.attributeValuesToObjectIDs allValues] valueForKeyPath:@"@distinctUnionOfArrays.self"];
|
||||
NSArray *allObjectIDs = [[self.cacheKeysToObjectIDs allValues] valueForKeyPath:@"@distinctUnionOfArrays.self"];
|
||||
return [allObjectIDs containsObject:object.objectID];
|
||||
}
|
||||
|
||||
|
||||
@@ -50,50 +50,48 @@
|
||||
*/
|
||||
@property (nonatomic, strong, readonly) NSManagedObjectContext *managedObjectContext;
|
||||
|
||||
///-----------------------------------------------------------------------------
|
||||
/// @name Caching Objects by Attribute
|
||||
///-----------------------------------------------------------------------------
|
||||
///------------------------------------
|
||||
/// @name Caching Objects by Attributes
|
||||
///------------------------------------
|
||||
|
||||
/**
|
||||
Caches all instances of an entity using the value for an attribute as the cache key.
|
||||
|
||||
@param entity The entity to cache all instances of.
|
||||
@param attributeName The attribute to cache the instances by.
|
||||
@param attributeNames The attributes to cache the instances by.
|
||||
*/
|
||||
- (void)cacheObjectsForEntity:(NSEntityDescription *)entity byAttribute:(NSString *)attributeName;
|
||||
- (void)cacheObjectsForEntity:(NSEntityDescription *)entity byAttributes:(NSArray *)attributeNames;
|
||||
|
||||
/**
|
||||
Returns a Boolean value indicating if all instances of an entity have been cached by a given attribute name.
|
||||
|
||||
@param entity The entity to check the cache status of.
|
||||
@param attributeName The attribute to check the cache status with.
|
||||
@param attributeNames The attributes to check the cache status with.
|
||||
@return YES if the cache has been loaded with instances with the given attribute, else NO.
|
||||
*/
|
||||
- (BOOL)isEntity:(NSEntityDescription *)entity cachedByAttribute:(NSString *)attributeName;
|
||||
- (BOOL)isEntity:(NSEntityDescription *)entity cachedByAttributes:(NSArray *)attributeNames;
|
||||
|
||||
/**
|
||||
Retrieves the first cached instance of a given entity where the specified attribute matches the given value.
|
||||
|
||||
@param entity The entity to search the cache for instances of.
|
||||
@param attributeName The attribute to search the cache for matches with.
|
||||
@param attributeValue The value of the attribute to return a match for.
|
||||
@param attributeValues The attribute values return a match for.
|
||||
@param context The managed object from which to retrieve the cached results.
|
||||
@return A matching managed object instance or nil.
|
||||
@raise NSInvalidArgumentException Raised if instances of the entity and attribute have not been cached.
|
||||
*/
|
||||
- (NSManagedObject *)objectForEntity:(NSEntityDescription *)entity withAttribute:(NSString *)attributeName value:(id)attributeValue inContext:(NSManagedObjectContext *)context;
|
||||
- (NSManagedObject *)objectForEntity:(NSEntityDescription *)entity withAttributeValues:(NSDictionary *)attributeValues inContext:(NSManagedObjectContext *)context;
|
||||
|
||||
/**
|
||||
Retrieves all cached instances of a given entity where the specified attribute matches the given value.
|
||||
|
||||
@param entity The entity to search the cache for instances of.
|
||||
@param attributeName The attribute to search the cache for matches with.
|
||||
@param attributeValue The value of the attribute to return a match for.
|
||||
@param attributeValues The attribute values return a match for.
|
||||
@param context The managed object from which to retrieve the cached results.
|
||||
@return All matching managed object instances or nil.
|
||||
@raise NSInvalidArgumentException Raised if instances of the entity and attribute have not been cached.
|
||||
*/
|
||||
- (NSArray *)objectsForEntity:(NSEntityDescription *)entity withAttribute:(NSString *)attributeName value:(id)attributeValue inContext:(NSManagedObjectContext *)context;
|
||||
- (NSArray *)objectsForEntity:(NSEntityDescription *)entity withAttributeValues:(NSDictionary *)attributeValues inContext:(NSManagedObjectContext *)context;
|
||||
|
||||
///-----------------------------------------------------------------------------
|
||||
// @name Accessing Underlying Caches
|
||||
@@ -106,7 +104,7 @@
|
||||
@param attributeName The attribute to retrieve the entity attribute cache object for.
|
||||
@return The entity attribute cache for the given entity and attribute, or nil if none was found.
|
||||
*/
|
||||
- (RKEntityByAttributeCache *)attributeCacheForEntity:(NSEntityDescription *)entity attribute:(NSString *)attributeName;
|
||||
- (RKEntityByAttributeCache *)attributeCacheForEntity:(NSEntityDescription *)entity attributes:(NSArray *)attributeNames;
|
||||
|
||||
/**
|
||||
Retrieves all entity attributes caches for a given entity.
|
||||
|
||||
@@ -46,58 +46,60 @@
|
||||
}
|
||||
|
||||
|
||||
- (void)cacheObjectsForEntity:(NSEntityDescription *)entity byAttribute:(NSString *)attributeName
|
||||
- (void)cacheObjectsForEntity:(NSEntityDescription *)entity byAttributes:(NSArray *)attributeNames
|
||||
{
|
||||
NSAssert(entity, @"Cannot cache objects for a nil entity");
|
||||
NSAssert(attributeName, @"Cannot cache objects without an attribute");
|
||||
RKEntityByAttributeCache *attributeCache = [self attributeCacheForEntity:entity attribute:attributeName];
|
||||
NSParameterAssert(entity);
|
||||
NSParameterAssert(attributeNames);
|
||||
RKEntityByAttributeCache *attributeCache = [self attributeCacheForEntity:entity attributes:attributeNames];
|
||||
if (attributeCache && !attributeCache.isLoaded) {
|
||||
[attributeCache load];
|
||||
} else {
|
||||
attributeCache = [[RKEntityByAttributeCache alloc] initWithEntity:entity attribute:attributeName managedObjectContext:self.managedObjectContext];
|
||||
attributeCache = [[RKEntityByAttributeCache alloc] initWithEntity:entity attributes:attributeNames managedObjectContext:self.managedObjectContext];
|
||||
[attributeCache load];
|
||||
[self.attributeCaches addObject:attributeCache];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isEntity:(NSEntityDescription *)entity cachedByAttribute:(NSString *)attributeName
|
||||
- (BOOL)isEntity:(NSEntityDescription *)entity cachedByAttributes:(NSArray *)attributeNames
|
||||
{
|
||||
NSAssert(entity, @"Cannot check cache status for a nil entity");
|
||||
NSAssert(attributeName, @"Cannot check cache status for a nil attribute");
|
||||
RKEntityByAttributeCache *attributeCache = [self attributeCacheForEntity:entity attribute:attributeName];
|
||||
NSParameterAssert(entity);
|
||||
NSParameterAssert(attributeNames);
|
||||
RKEntityByAttributeCache *attributeCache = [self attributeCacheForEntity:entity attributes:attributeNames];
|
||||
return (attributeCache && attributeCache.isLoaded);
|
||||
}
|
||||
|
||||
- (NSManagedObject *)objectForEntity:(NSEntityDescription *)entity withAttribute:(NSString *)attributeName value:(id)attributeValue inContext:(NSManagedObjectContext *)context
|
||||
- (NSManagedObject *)objectForEntity:(NSEntityDescription *)entity withAttributeValues:(NSDictionary *)attributeValues inContext:(NSManagedObjectContext *)context
|
||||
{
|
||||
NSAssert(entity, @"Cannot retrieve cached objects with a nil entity");
|
||||
NSAssert(attributeName, @"Cannot retrieve cached objects by a nil entity");
|
||||
RKEntityByAttributeCache *attributeCache = [self attributeCacheForEntity:entity attribute:attributeName];
|
||||
NSParameterAssert(entity);
|
||||
NSParameterAssert(attributeValues);
|
||||
NSParameterAssert(context);
|
||||
RKEntityByAttributeCache *attributeCache = [self attributeCacheForEntity:entity attributes:[attributeValues allKeys]];
|
||||
if (attributeCache) {
|
||||
return [attributeCache objectWithAttributeValue:attributeValue inContext:context];
|
||||
return [attributeCache objectWithAttributeValues:attributeValues inContext:context];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSArray *)objectsForEntity:(NSEntityDescription *)entity withAttribute:(NSString *)attributeName value:(id)attributeValue inContext:(NSManagedObjectContext *)context
|
||||
- (NSArray *)objectsForEntity:(NSEntityDescription *)entity withAttributeValues:(NSDictionary *)attributeValues inContext:(NSManagedObjectContext *)context
|
||||
{
|
||||
NSAssert(entity, @"Cannot retrieve cached objects with a nil entity");
|
||||
NSAssert(attributeName, @"Cannot retrieve cached objects by a nil entity");
|
||||
RKEntityByAttributeCache *attributeCache = [self attributeCacheForEntity:entity attribute:attributeName];
|
||||
NSParameterAssert(entity);
|
||||
NSParameterAssert(attributeValues);
|
||||
NSParameterAssert(context);
|
||||
RKEntityByAttributeCache *attributeCache = [self attributeCacheForEntity:entity attributes:[attributeValues allKeys]];
|
||||
if (attributeCache) {
|
||||
return [attributeCache objectsWithAttributeValue:attributeValue inContext:context];
|
||||
return [attributeCache objectsWithAttributeValues:attributeValues inContext:context];
|
||||
}
|
||||
|
||||
return [NSSet set];
|
||||
}
|
||||
|
||||
- (RKEntityByAttributeCache *)attributeCacheForEntity:(NSEntityDescription *)entity attribute:(NSString *)attributeName
|
||||
- (RKEntityByAttributeCache *)attributeCacheForEntity:(NSEntityDescription *)entity attributes:(NSArray *)attributeNames
|
||||
{
|
||||
NSAssert(entity, @"Cannot retrieve attribute cache for a nil entity");
|
||||
NSAssert(attributeName, @"Cannot retrieve attribute cache for a nil attribute");
|
||||
NSParameterAssert(entity);
|
||||
NSParameterAssert(attributeNames);
|
||||
for (RKEntityByAttributeCache *cache in self.attributeCaches) {
|
||||
if ([cache.entity isEqual:entity] && [cache.attribute isEqualToString:attributeName]) {
|
||||
if ([cache.entity isEqual:entity] && [cache.attributes isEqualToArray:attributeNames]) {
|
||||
return cache;
|
||||
}
|
||||
}
|
||||
|
||||
39
Code/CoreData/RKEntityIdentifier.h
Normal file
39
Code/CoreData/RKEntityIdentifier.h
Normal file
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// RKEntityIdentifier.h
|
||||
// RestKit
|
||||
//
|
||||
// Created by Blake Watters on 11/20/12.
|
||||
// Copyright (c) 2012 RestKit. All rights reserved.
|
||||
//
|
||||
|
||||
#import <CoreData/CoreData.h>
|
||||
|
||||
extern NSString * const RKEntityIdentifierUserInfoKey;
|
||||
|
||||
@class RKManagedObjectStore;
|
||||
|
||||
// RKEntityIdentifier | RKManagedObjectIdentifier | RKEntityIdentity | RKResourceIdentity | RKEntityKey | RKIdentifier
|
||||
@interface RKEntityIdentifier : NSObject
|
||||
|
||||
@property (nonatomic, strong, readonly) NSEntityDescription *entity;
|
||||
@property (nonatomic, copy, readonly) NSArray *attributes;
|
||||
|
||||
// Convenience method
|
||||
// identifierWithEntityName:???
|
||||
// entityIdentifierWithName:
|
||||
+ (id)identifierWithEntityName:(NSString *)entityName attributes:(NSArray *)attributes inManagedObjectStore:(RKManagedObjectStore *)managedObjectStore;
|
||||
|
||||
// Designated initializer
|
||||
- (id)initWithEntity:(NSEntityDescription *)entity attributes:(NSArray *)attributes;
|
||||
|
||||
// Optional predicate for filtering matches
|
||||
@property (nonatomic, copy) NSPredicate *predicate;
|
||||
|
||||
///-------------------------------------------
|
||||
/// @name Inferring Identifiers from the Model
|
||||
///-------------------------------------------
|
||||
|
||||
// NOTE: Add not about checking the entity's userInfo
|
||||
+ (RKEntityIdentifier *)inferredIdentifierForEntity:(NSEntityDescription *)entity;
|
||||
|
||||
@end
|
||||
117
Code/CoreData/RKEntityIdentifier.m
Normal file
117
Code/CoreData/RKEntityIdentifier.m
Normal file
@@ -0,0 +1,117 @@
|
||||
//
|
||||
// RKEntityIdentifier.m
|
||||
// RestKit
|
||||
//
|
||||
// Created by Blake Watters on 11/20/12.
|
||||
// Copyright (c) 2012 RestKit. All rights reserved.
|
||||
//
|
||||
|
||||
#import "RKEntityIdentifier.h"
|
||||
#import "RKManagedObjectStore.h"
|
||||
|
||||
NSString * const RKEntityIdentifierUserInfoKey = @"RKEntityIdentifierAttributes";
|
||||
|
||||
static NSArray *RKEntityIdentifierAttributesFromUserInfoOfEntity(NSEntityDescription *entity)
|
||||
{
|
||||
id userInfoValue = [entity userInfo][RKEntityIdentifierUserInfoKey];
|
||||
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 '%@' (%@)", RKEntityIdentifierUserInfoKey, [entity name], attributeName, [attributeName class]];
|
||||
}
|
||||
|
||||
NSAttributeDescription *attribute = [entity attributesByName][attributeName];
|
||||
if (! attribute) {
|
||||
[NSException raise:NSInvalidArgumentException format:@"Invalid identifier attribute specified in user info key '%@' of entity '%@': no attribue was found with the name '%@'", RKEntityIdentifierUserInfoKey, [entity name], attributeName];
|
||||
}
|
||||
|
||||
[attributes addObject:attribute];
|
||||
}];
|
||||
return attributes;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Given 'Human', returns 'humanID'; Given 'AmenityReview' returns 'amenityReviewID'
|
||||
static NSString *RKEntityIdentifierAttributeNameForEntity(NSEntityDescription *entity)
|
||||
{
|
||||
NSString *entityName = [entity name];
|
||||
NSString *lowerCasedFirstCharacter = [[entityName substringToIndex:1] lowercaseString];
|
||||
return [NSString stringWithFormat:@"%@%@ID", lowerCasedFirstCharacter, [entityName substringFromIndex:1]];
|
||||
}
|
||||
|
||||
static NSArray *RKEntityIdentifierAttributeNames()
|
||||
{
|
||||
return [NSArray arrayWithObjects:@"identifier", @"ID", @"URL", @"url", nil];
|
||||
}
|
||||
|
||||
static NSArray *RKArrayOfAttributesForEntityFromAttributesOrNames(NSEntityDescription *entity, NSArray *attributesOrNames)
|
||||
{
|
||||
NSMutableArray *attributes = [NSMutableArray arrayWithCapacity:[attributesOrNames count]];
|
||||
for (id attributeOrName in attributesOrNames) {
|
||||
if ([attributeOrName isKindOfClass:[NSAttributeDescription class]]) {
|
||||
if (! [[entity properties] containsObject:attributeOrName]) [NSException raise:NSInvalidArgumentException format:@"Invalid attribute value '%@' given for entity identifer: not found in the '%@' entity", attributeOrName, [entity name]];
|
||||
[attributes addObject:attributeOrName];
|
||||
} else if ([attributeOrName isKindOfClass:[NSString class]]) {
|
||||
NSAttributeDescription *attribute = [entity attributesByName][attributeOrName];
|
||||
if (!attribute) [NSException raise:NSInvalidArgumentException format:@"Invalid attribute '%@': no attribute was found for the given name in the '%@' entity.", attributeOrName, [entity name]];
|
||||
[attributes addObject:attribute];
|
||||
} else {
|
||||
[NSException raise:NSInvalidArgumentException format:@"Invalid value provided for entity identifier attribute: Acceptable values are either `NSAttributeDescription` or `NSString` objects."];
|
||||
}
|
||||
}
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
@interface RKEntityIdentifier ()
|
||||
@property (nonatomic, strong, readwrite) NSEntityDescription *entity;
|
||||
@property (nonatomic, copy, readwrite) NSArray *attributes;
|
||||
@end
|
||||
|
||||
@implementation RKEntityIdentifier
|
||||
|
||||
+ (id)identifierWithEntityName:(NSString *)entityName attributes:(NSArray *)attributes inManagedObjectStore:(RKManagedObjectStore *)managedObjectStore
|
||||
{
|
||||
NSEntityDescription *entity = [managedObjectStore.managedObjectModel entitiesByName][entityName];
|
||||
return [[self alloc] initWithEntity:entity attributes:attributes];
|
||||
}
|
||||
|
||||
- (id)initWithEntity:(NSEntityDescription *)entity attributes:(NSArray *)attributes
|
||||
{
|
||||
NSParameterAssert(entity);
|
||||
NSParameterAssert(attributes);
|
||||
NSAssert([attributes count], @"At least one attribute must be provided to identify managed objects");
|
||||
self = [self init];
|
||||
if (self) {
|
||||
self.entity = entity;
|
||||
self.attributes = RKArrayOfAttributesForEntityFromAttributesOrNames(entity, attributes);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Idetifier Inference
|
||||
|
||||
+ (RKEntityIdentifier *)inferredIdentifierForEntity:(NSEntityDescription *)entity
|
||||
{
|
||||
NSArray *attributes = RKEntityIdentifierAttributesFromUserInfoOfEntity(entity);
|
||||
if (attributes) {
|
||||
return [[RKEntityIdentifier alloc] initWithEntity:entity attributes:attributes];
|
||||
}
|
||||
|
||||
NSMutableArray *identifyingAttributes = [NSMutableArray arrayWithObject:RKEntityIdentifierAttributeNameForEntity(entity)];
|
||||
[identifyingAttributes addObjectsFromArray:RKEntityIdentifierAttributeNames()];
|
||||
for (NSString *attributeName in identifyingAttributes) {
|
||||
NSAttributeDescription *attribute = [entity attributesByName][attributeName];
|
||||
if (attribute) {
|
||||
return [[RKEntityIdentifier alloc] initWithEntity:entity attributes:@[ attribute ]];
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -20,13 +20,26 @@
|
||||
|
||||
#import <CoreData/CoreData.h>
|
||||
#import "RKObjectMapping.h"
|
||||
#import "RKConnectionMapping.h"
|
||||
#import "RKConnectionDescription.h"
|
||||
#import "RKMacros.h"
|
||||
#import "RKEntityIdentifier.h"
|
||||
|
||||
@class RKManagedObjectStore;
|
||||
|
||||
/**
|
||||
RKEntityMapping objects model an object mapping with a Core Data destination entity.
|
||||
|
||||
## Entity Identification
|
||||
|
||||
TBD
|
||||
|
||||
### Inferring Entity Identifiers
|
||||
|
||||
TBD
|
||||
|
||||
## Connecting Relationships
|
||||
|
||||
TBD
|
||||
*/
|
||||
@interface RKEntityMapping : RKObjectMapping
|
||||
|
||||
@@ -62,58 +75,63 @@
|
||||
*/
|
||||
@property (nonatomic, strong) NSEntityDescription *entity;
|
||||
|
||||
/**
|
||||
The name of the attribute on the destination entity that acts as the primary key for instances
|
||||
of the entity in the remote backend system. Used to uniquely identify objects within the store
|
||||
so that existing objects are updated rather than creating new ones.
|
||||
// The index for finding existing objects. Can be compound.
|
||||
@property (nonatomic, copy) RKEntityIdentifier *entityIdentifier;
|
||||
|
||||
@warning Note that primaryKeyAttribute defaults to the primaryKeyAttribute configured
|
||||
on the NSEntityDescription for the entity targetted by the receiving mapping. This provides
|
||||
flexibility in cases where a single entity is the target of many mappings with differing
|
||||
primary key definitions.
|
||||
// Setting an existing entity identifier replaces it...
|
||||
- (void)setEntityIdentifier:(RKEntityIdentifier *)entityIdentifier forRelationship:(NSString *)relationshipName;
|
||||
|
||||
If the `primaryKeyAttribute` is set on an `RKEntityMapping` that targets an entity with a
|
||||
nil primaryKeyAttribute, then the primaryKeyAttribute will be set on the entity as well for
|
||||
convenience and backwards compatibility. This may change in the future.
|
||||
// NOTE: This returns explicitly set value, then the entityIdentifier for the relationship mapping
|
||||
- (RKEntityIdentifier *)entityIdentifierForRelationship:(NSString *)relationshipName;
|
||||
|
||||
@see `[NSEntityDescription primaryKeyAttribute]`
|
||||
*/
|
||||
// TODO: Make me readonly
|
||||
@property (nonatomic, strong) NSString *primaryKeyAttribute;
|
||||
///**
|
||||
// The name of the attribute on the destination entity that acts as the primary key for instances
|
||||
// of the entity in the remote backend system. Used to uniquely identify objects within the store
|
||||
// so that existing objects are updated rather than creating new ones.
|
||||
//
|
||||
// @warning Note that primaryKeyAttribute defaults to the primaryKeyAttribute configured
|
||||
// on the NSEntityDescription for the entity targetted by the receiving mapping. This provides
|
||||
// flexibility in cases where a single entity is the target of many mappings with differing
|
||||
// primary key definitions.
|
||||
//
|
||||
// If the `primaryKeyAttribute` is set on an `RKEntityMapping` that targets an entity with a
|
||||
// nil primaryKeyAttribute, then the primaryKeyAttribute will be set on the entity as well for
|
||||
// convenience and backwards compatibility. This may change in the future.
|
||||
//
|
||||
// @see `[NSEntityDescription primaryKeyAttribute]`
|
||||
// */
|
||||
//// TODO: Make me readonly
|
||||
//@property (nonatomic, strong) NSString *primaryKeyAttribute;
|
||||
|
||||
/**
|
||||
Retrieves an array of RKConnectionMapping objects for connecting the receiver's relationships
|
||||
by primary key.
|
||||
|
||||
@see `RKConnectionMapping`
|
||||
*/
|
||||
@property (weak, nonatomic, readonly) NSArray *connectionMappings;
|
||||
@property (weak, nonatomic, readonly) NSArray *connections;
|
||||
|
||||
/**
|
||||
Adds a connection mapping to the receiver.
|
||||
|
||||
@param connectionMapping The connection mapping to be added.
|
||||
*/
|
||||
- (void)addConnectionMapping:(RKConnectionMapping *)connectionMapping;
|
||||
- (void)addConnectionMappingsFromArray:(NSArray *)arrayOfConnectionMappings;
|
||||
- (void)addConnection:(RKConnectionDescription *)connection;
|
||||
- (void)removeConnection:(RKConnectionDescription *)connection;
|
||||
- (void)addConnectionForRelationship:(id)relationshipOrName connectedBy:(id)connectionSpecifier;
|
||||
- (RKConnectionDescription *)connectionForRelationship:(id)relationshipOrName;
|
||||
|
||||
// Convenience method.
|
||||
- (RKConnectionMapping *)addConnectionMappingForRelationshipForName:(NSString *)relationshipName
|
||||
fromSourceKeyPath:(NSString *)sourceKeyPath
|
||||
toKeyPath:(NSString *)destinationKeyPath
|
||||
matcher:(RKDynamicMappingMatcher *)matcher;
|
||||
|
||||
/**
|
||||
Removes a connection mapping from the receiver.
|
||||
|
||||
@param connectionMapping The connection mapping to be added.
|
||||
*/
|
||||
- (void)removeConnectionMapping:(RKConnectionMapping *)connectionMapping;
|
||||
///------------------------------------------
|
||||
/// @name Retrieving Default Attribute Values
|
||||
///------------------------------------------
|
||||
|
||||
/**
|
||||
Returns the default value for the specified attribute as expressed in the Core Data entity definition. This value will
|
||||
be assigned if the object mapping is applied and a value for a missing attribute is not present in the payload.
|
||||
*/
|
||||
- (id)defaultValueForMissingAttribute:(NSString *)attributeName;
|
||||
- (id)defaultValueForAttribute:(NSString *)attributeName;
|
||||
|
||||
///----------------------------------------------
|
||||
/// @name Configuring Entity Identifier Inference
|
||||
///----------------------------------------------
|
||||
|
||||
// setInfersEntityIdentifiers:(BOOL) | setShouldInferEntityIdentifiers:
|
||||
// setEntityIdentificationInferenceEnabled: | :
|
||||
+ (void)setEntityIdentifierInferenceEnabled:(BOOL)enabled; // Default YES
|
||||
+ (BOOL)isEntityIdentifierInferenceEnabled;
|
||||
|
||||
@end
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#import "RKManagedObjectStore.h"
|
||||
#import "RKDynamicMappingMatcher.h"
|
||||
#import "RKPropertyInspector+CoreData.h"
|
||||
#import "NSEntityDescription+RKAdditions.h"
|
||||
#import "RKLog.h"
|
||||
#import "RKRelationshipMapping.h"
|
||||
#import "RKObjectUtilities.h"
|
||||
@@ -31,14 +30,33 @@
|
||||
#undef RKLogComponent
|
||||
#define RKLogComponent RKlcl_cRestKitCoreData
|
||||
|
||||
static BOOL entityIdentifierInferenceEnabled = YES;
|
||||
|
||||
static void RKInferIdentifiersForEntityMapping(RKEntityMapping *entityMapping)
|
||||
{
|
||||
if (! [RKEntityMapping isEntityIdentifierInferenceEnabled]) return;
|
||||
|
||||
entityMapping.entityIdentifier = [RKEntityIdentifier inferredIdentifierForEntity:entityMapping.entity];
|
||||
[[entityMapping.entity relationshipsByName] enumerateKeysAndObjectsUsingBlock:^(NSString *relationshipName, NSRelationshipDescription *relationship, BOOL *stop) {
|
||||
RKEntityIdentifier *entityIdentififer = [RKEntityIdentifier inferredIdentifierForEntity:relationship.destinationEntity];
|
||||
if (entityIdentififer) {
|
||||
[entityMapping setEntityIdentifier:entityIdentififer forRelationship:relationshipName];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
@interface RKObjectMapping (Private)
|
||||
- (NSString *)transformSourceKeyPath:(NSString *)keyPath;
|
||||
@end
|
||||
|
||||
@interface RKEntityMapping ()
|
||||
@property (nonatomic, weak, readwrite) Class objectClass;
|
||||
@property (nonatomic, strong) NSMutableArray *mutableConnections;
|
||||
@property (nonatomic, strong) NSMutableDictionary *relationshipNamesToEntityIdentifiers;
|
||||
@end
|
||||
|
||||
@implementation RKEntityMapping
|
||||
|
||||
|
||||
+ (id)mappingForClass:(Class)objectClass
|
||||
{
|
||||
@throw [NSException exceptionWithName:NSInternalInconsistencyException
|
||||
@@ -60,9 +78,7 @@
|
||||
self = [self initWithClass:objectClass];
|
||||
if (self) {
|
||||
self.entity = entity;
|
||||
|
||||
[self addObserver:self forKeyPath:@"entity" options:NSKeyValueObservingOptionInitial context:nil];
|
||||
[self addObserver:self forKeyPath:@"primaryKeyAttribute" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:nil];
|
||||
RKInferIdentifiersForEntityMapping(self);
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -73,61 +89,106 @@
|
||||
self = [super initWithClass:objectClass];
|
||||
if (self) {
|
||||
self.mutableConnections = [NSMutableArray array];
|
||||
self.relationshipNamesToEntityIdentifiers = [NSMutableDictionary dictionary];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
- (id)copyWithZone:(NSZone *)zone
|
||||
{
|
||||
[self removeObserver:self forKeyPath:@"entity"];
|
||||
[self removeObserver:self forKeyPath:@"primaryKeyAttribute"];
|
||||
RKEntityMapping *copy = [super copyWithZone:zone];
|
||||
copy.entityIdentifier = [self.entityIdentifier copy];
|
||||
|
||||
for (RKConnectionDescription *connection in self.connections) {
|
||||
[copy addConnection:[connection copy]];
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
- (RKConnectionMapping *)connectionMappingForRelationshipWithName:(NSString *)relationshipName
|
||||
- (RKConnectionDescription *)connectionForRelationship:(id)relationshipOrName
|
||||
{
|
||||
for (RKConnectionMapping *connection in self.connectionMappings) {
|
||||
if ([connection.relationship.name isEqualToString:relationshipName]) {
|
||||
NSAssert([relationshipOrName isKindOfClass:[NSString class]] || [relationshipOrName isKindOfClass:[NSRelationshipDescription class]], @"Relationship specifier must be a name or a relationship description");
|
||||
NSString *relationshipName = [relationshipOrName isKindOfClass:[NSRelationshipDescription class]] ? [(NSRelationshipDescription *)relationshipOrName name] : relationshipOrName;
|
||||
for (RKConnectionDescription *connection in self.connections) {
|
||||
if ([[connection.relationship name] isEqualToString:relationshipName]) {
|
||||
return connection;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)addConnectionMapping:(RKConnectionMapping *)mapping
|
||||
- (void)addConnection:(RKConnectionDescription *)connection
|
||||
{
|
||||
NSParameterAssert(mapping);
|
||||
RKConnectionMapping *connectionMapping = [self connectionMappingForRelationshipWithName:mapping.relationship.name];
|
||||
NSAssert(connectionMapping == nil, @"Cannot add connect relationship %@ by primary key, a mapping already exists.", mapping.relationship.name);
|
||||
NSParameterAssert(connection);
|
||||
RKConnectionDescription *existingConnection = [self connectionForRelationship:connection.relationship];
|
||||
NSAssert(existingConnection == nil, @"Cannot add connection: An existing connection already exists for the '%@' relationship.", connection.relationship.name);
|
||||
NSAssert(self.mutableConnections, @"self.mutableConnections should not be nil");
|
||||
[self.mutableConnections addObject:mapping];
|
||||
[self.mutableConnections addObject:connection];
|
||||
}
|
||||
|
||||
- (void)addConnectionMappingsFromArray:(NSArray *)arrayOfConnectionMappings
|
||||
- (void)removeConnection:(RKConnectionDescription *)connection
|
||||
{
|
||||
for (RKConnectionMapping *connectionMapping in arrayOfConnectionMappings) {
|
||||
[self addConnectionMapping:connectionMapping];
|
||||
[self.mutableConnections removeObject:connection];
|
||||
}
|
||||
|
||||
- (NSArray *)connections
|
||||
{
|
||||
return [NSArray arrayWithArray:self.mutableConnections];
|
||||
}
|
||||
|
||||
- (void)addConnectionForRelationship:(id)relationshipOrName connectedBy:(id)connectionSpecifier
|
||||
{
|
||||
NSRelationshipDescription *relationship = [relationshipOrName isKindOfClass:[NSRelationshipDescription class]] ? relationshipOrName : [self.entity relationshipsByName][relationshipOrName];
|
||||
NSAssert(relationship, @"No relatiobship was found named '%@' in the '%@' entity", relationshipOrName, [self.entity name]);
|
||||
RKConnectionDescription *connection = nil;
|
||||
if ([connectionSpecifier isKindOfClass:[NSString class]]) {
|
||||
NSString *sourceAttribute = connectionSpecifier;
|
||||
NSString *destinationAttribute = [self transformSourceKeyPath:sourceAttribute];
|
||||
connection = [[RKConnectionDescription alloc] initWithRelationship:relationship attributes:@{ sourceAttribute: destinationAttribute }];
|
||||
} else if ([connectionSpecifier isKindOfClass:[NSArray class]]) {
|
||||
NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithCapacity:[connectionSpecifier count]];
|
||||
for (NSString *sourceAttribute in connectionSpecifier) {
|
||||
NSString *destinationAttribute = [self transformSourceKeyPath:sourceAttribute];
|
||||
attributes[sourceAttribute] = destinationAttribute;
|
||||
}
|
||||
connection = [[RKConnectionDescription alloc] initWithRelationship:relationship attributes:attributes];
|
||||
} else if ([connectionSpecifier isKindOfClass:[NSDictionary class]]) {
|
||||
connection = [[RKConnectionDescription alloc] initWithRelationship:relationship attributes:connectionSpecifier];
|
||||
} else {
|
||||
[NSException raise:NSInvalidArgumentException format:@"Connections can only be described using `NSString`, `NSArray`, or `NSDictionary` objects. Instead, got: %@", connectionSpecifier];
|
||||
}
|
||||
|
||||
[self.mutableConnections addObject:connection];
|
||||
}
|
||||
|
||||
- (RKConnectionMapping *)addConnectionMappingForRelationshipForName:(NSString *)relationshipName
|
||||
fromSourceKeyPath:(NSString *)sourceKeyPath
|
||||
toKeyPath:(NSString *)destinationKeyPath
|
||||
matcher:(RKDynamicMappingMatcher *)matcher
|
||||
- (void)setEntityIdentifier:(RKEntityIdentifier *)entityIdentifier
|
||||
{
|
||||
NSRelationshipDescription *relationship = [[self.entity propertiesByName] objectForKey:relationshipName];
|
||||
NSAssert(relationship, @"Unable to find a relationship named '%@' in the entity: %@", relationshipName, self.entity);
|
||||
RKConnectionMapping *connectionMapping = [[RKConnectionMapping alloc] initWithRelationship:relationship sourceKeyPath:sourceKeyPath destinationKeyPath:destinationKeyPath matcher:matcher];
|
||||
[self addConnectionMapping:connectionMapping];
|
||||
return connectionMapping;
|
||||
NSAssert(entityIdentifier == nil || [entityIdentifier.entity isKindOfEntity:self.entity], @"Invalid entity identifier value: The identifier given is for the '%@' entity.", [entityIdentifier.entity name]);
|
||||
_entityIdentifier = entityIdentifier;
|
||||
}
|
||||
|
||||
- (void)removeConnectionMapping:(RKConnectionMapping *)connectionMapping
|
||||
- (void)setEntityIdentifier:(RKEntityIdentifier *)entityIdentifier forRelationship:(NSString *)relationshipName
|
||||
{
|
||||
[self.mutableConnections removeObject:connectionMapping];
|
||||
NSRelationshipDescription *relationship = [self.entity relationshipsByName][relationshipName];
|
||||
NSAssert(relationship, @"Cannot set entity identififer for relationship '%@': no relationship found for that name.", relationshipName);
|
||||
NSAssert([[relationship destinationEntity] isKindOfEntity:entityIdentifier.entity], @"Cannot set entity identifier for relationship '%@': the given relationship identifier is for the '%@' entity, but the '%@' entity was expected.", relationshipName, [entityIdentifier.entity name], [[relationship destinationEntity] name]);
|
||||
self.relationshipNamesToEntityIdentifiers[relationshipName] = entityIdentifier;
|
||||
}
|
||||
|
||||
- (id)defaultValueForMissingAttribute:(NSString *)attributeName
|
||||
- (RKEntityIdentifier *)entityIdentifierForRelationship:(NSString *)relationshipName
|
||||
{
|
||||
RKEntityIdentifier *entityIdentifier = self.relationshipNamesToEntityIdentifiers[relationshipName];
|
||||
if (! entityIdentifier) {
|
||||
RKRelationshipMapping *relationshipMapping = [self propertyMappingsByDestinationKeyPath][relationshipName];
|
||||
entityIdentifier = [relationshipMapping.mapping isKindOfClass:[RKEntityIdentifier class]] ? [(RKEntityMapping *)relationshipMapping.mapping entityIdentifier] : nil;
|
||||
}
|
||||
|
||||
return entityIdentifier;
|
||||
}
|
||||
|
||||
- (id)defaultValueForAttribute:(NSString *)attributeName
|
||||
{
|
||||
NSAttributeDescription *desc = [[self.entity attributesByName] valueForKey:attributeName];
|
||||
return [desc defaultValue];
|
||||
@@ -143,25 +204,14 @@
|
||||
return propertyClass;
|
||||
}
|
||||
|
||||
/*
|
||||
Allows the primaryKeyAttributeName property on the NSEntityDescription to configure the mapping and vice-versa
|
||||
*/
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
|
||||
+ (void)setEntityIdentifierInferenceEnabled:(BOOL)enabled
|
||||
{
|
||||
if ([keyPath isEqualToString:@"entity"]) {
|
||||
if (! self.primaryKeyAttribute) {
|
||||
self.primaryKeyAttribute = [self.entity primaryKeyAttributeName];
|
||||
}
|
||||
} else if ([keyPath isEqualToString:@"primaryKeyAttribute"]) {
|
||||
if (! self.entity.primaryKeyAttribute) {
|
||||
self.entity.primaryKeyAttributeName = self.primaryKeyAttribute;
|
||||
}
|
||||
}
|
||||
entityIdentifierInferenceEnabled = enabled;
|
||||
}
|
||||
|
||||
- (NSArray *)connectionMappings
|
||||
+ (BOOL)isEntityIdentifierInferenceEnabled
|
||||
{
|
||||
return [NSArray arrayWithArray:self.mutableConnections];
|
||||
return entityIdentifierInferenceEnabled;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
//
|
||||
|
||||
#import "RKFetchRequestManagedObjectCache.h"
|
||||
#import "NSEntityDescription+RKAdditions.h"
|
||||
#import "RKLog.h"
|
||||
#import "RKPropertyInspector.h"
|
||||
#import "RKPropertyInspector+CoreData.h"
|
||||
@@ -16,37 +15,56 @@
|
||||
#undef RKLogComponent
|
||||
#define RKLogComponent RKlcl_cRestKitCoreData
|
||||
|
||||
static NSString *RKPredicateCacheKeyForAttributes(NSArray *attributeNames)
|
||||
{
|
||||
return [[attributeNames sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] componentsJoinedByString:@":"];
|
||||
}
|
||||
|
||||
// NOTE: We build a dynamic format string here because `NSCompoundPredicate` does not support use of substiution variables
|
||||
static NSPredicate *RKPredicateWithSubsitutionVariablesForAttributes(NSArray *attributeNames)
|
||||
{
|
||||
NSMutableArray *formatFragments = [NSMutableArray arrayWithCapacity:[attributeNames count]];
|
||||
for (NSString *attributeName in attributeNames) {
|
||||
NSString *formatFragment = [NSString stringWithFormat:@"%@ = $%@", attributeName, attributeName];
|
||||
[formatFragments addObject:formatFragment];
|
||||
}
|
||||
|
||||
return [NSPredicate predicateWithFormat:[formatFragments componentsJoinedByString:@" AND "]];
|
||||
}
|
||||
|
||||
@interface RKFetchRequestManagedObjectCache ()
|
||||
@property (nonatomic, strong) NSCache *predicateCache;
|
||||
@end
|
||||
|
||||
@implementation RKFetchRequestManagedObjectCache
|
||||
|
||||
- (NSArray *)findInstancesOfEntity:(NSEntityDescription *)entity
|
||||
withPrimaryKeyAttribute:(NSString *)primaryKeyAttribute
|
||||
value:(id)primaryKeyValue
|
||||
inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.predicateCache = [NSCache new];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSArray *)managedObjectsWithEntity:(NSEntityDescription *)entity
|
||||
attributeValues:(NSDictionary *)attributeValues
|
||||
inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext
|
||||
{
|
||||
|
||||
NSAssert(entity, @"Cannot find existing managed object without a target class");
|
||||
NSAssert(primaryKeyAttribute, @"Cannot find existing managed object instance without mapping that defines a primaryKeyAttribute");
|
||||
NSAssert(attributeValues, @"Cannot retrieve cached objects without attribute values to identify them with.");
|
||||
NSAssert(managedObjectContext, @"Cannot find existing managed object with a nil context");
|
||||
|
||||
id searchValue = primaryKeyValue;
|
||||
Class type = [[RKPropertyInspector sharedInspector] classForPropertyNamed:primaryKeyAttribute ofEntity:entity];
|
||||
if (type && ([type isSubclassOfClass:[NSString class]] && NO == [primaryKeyValue isKindOfClass:[NSString class]])) {
|
||||
searchValue = [NSString stringWithFormat:@"%@", primaryKeyValue];
|
||||
} else if (type && ([type isSubclassOfClass:[NSNumber class]] && NO == [primaryKeyValue isKindOfClass:[NSNumber class]])) {
|
||||
if ([primaryKeyValue isKindOfClass:[NSString class]]) {
|
||||
searchValue = [NSNumber numberWithDouble:[(NSString *)primaryKeyValue doubleValue]];
|
||||
}
|
||||
}
|
||||
|
||||
// Use cached predicate if primary key matches
|
||||
NSPredicate *predicate = nil;
|
||||
if ([entity.primaryKeyAttributeName isEqualToString:primaryKeyAttribute]) {
|
||||
predicate = [entity predicateForPrimaryKeyAttributeWithValue:searchValue];
|
||||
} else {
|
||||
// Parse a predicate
|
||||
predicate = [NSPredicate predicateWithFormat:@"%K = %@", primaryKeyAttribute, searchValue];
|
||||
|
||||
NSString *predicateCacheKey = RKPredicateCacheKeyForAttributes([attributeValues allKeys]);
|
||||
NSPredicate *substitutionPredicate = [self.predicateCache objectForKey:predicateCacheKey];
|
||||
if (! substitutionPredicate) {
|
||||
substitutionPredicate = RKPredicateWithSubsitutionVariablesForAttributes([attributeValues allKeys]);
|
||||
[self.predicateCache setObject:substitutionPredicate forKey:predicateCacheKey];
|
||||
}
|
||||
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:[entity name]];
|
||||
fetchRequest.predicate = predicate;
|
||||
fetchRequest.predicate = [substitutionPredicate predicateWithSubstitutionVariables:attributeValues];
|
||||
NSError *error = nil;
|
||||
NSArray *objects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
|
||||
if (! objects) {
|
||||
@@ -57,18 +75,4 @@
|
||||
return objects;
|
||||
}
|
||||
|
||||
- (NSManagedObject *)findInstanceOfEntity:(NSEntityDescription *)entity
|
||||
withPrimaryKeyAttribute:(NSString *)primaryKeyAttribute
|
||||
value:(id)primaryKeyValue
|
||||
inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext
|
||||
{
|
||||
NSArray *objects = [self findInstancesOfEntity:entity withPrimaryKeyAttribute:primaryKeyAttribute value:primaryKeyValue inManagedObjectContext:managedObjectContext];
|
||||
|
||||
NSManagedObject *object = nil;
|
||||
if ([objects count] > 0) {
|
||||
object = [objects objectAtIndex:0];
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -52,38 +52,23 @@
|
||||
userInfo:nil];
|
||||
}
|
||||
|
||||
|
||||
- (NSManagedObject *)findInstanceOfEntity:(NSEntityDescription *)entity
|
||||
withPrimaryKeyAttribute:(NSString *)primaryKeyAttribute
|
||||
value:(id)primaryKeyValue
|
||||
inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext
|
||||
- (NSArray *)managedObjectsWithEntity:(NSEntityDescription *)entity
|
||||
attributeValues:(NSDictionary *)attributeValues
|
||||
inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext
|
||||
{
|
||||
NSAssert(self.entityCache, @"Entity cache cannot be nil.");
|
||||
if (! [self.entityCache isEntity:entity cachedByAttribute:primaryKeyAttribute]) {
|
||||
RKLogInfo(@"Caching instances of Entity '%@' by primary key attribute '%@'", entity.name, primaryKeyAttribute);
|
||||
[self.entityCache cacheObjectsForEntity:entity byAttribute:primaryKeyAttribute];
|
||||
RKEntityByAttributeCache *attributeCache = [self.entityCache attributeCacheForEntity:entity attribute:primaryKeyAttribute];
|
||||
NSParameterAssert(entity);
|
||||
NSParameterAssert(attributeValues);
|
||||
NSParameterAssert(managedObjectContext);
|
||||
|
||||
NSArray *attributes = [attributeValues allKeys];
|
||||
if (! [self.entityCache isEntity:entity cachedByAttributes:attributes]) {
|
||||
RKLogInfo(@"Caching instances of Entity '%@' by attributes '%@'", entity.name, [attributes componentsJoinedByString:@", "]);
|
||||
[self.entityCache cacheObjectsForEntity:entity byAttributes:attributes];
|
||||
RKEntityByAttributeCache *attributeCache = [self.entityCache attributeCacheForEntity:entity attributes:attributes];
|
||||
RKLogTrace(@"Cached %ld objects", (long)[attributeCache count]);
|
||||
}
|
||||
|
||||
return [self.entityCache objectForEntity:entity withAttribute:primaryKeyAttribute value:primaryKeyValue inContext:managedObjectContext];
|
||||
}
|
||||
|
||||
- (NSArray *)findInstancesOfEntity:(NSEntityDescription *)entity
|
||||
withPrimaryKeyAttribute:(NSString *)primaryKeyAttribute
|
||||
value:(id)primaryKeyValue
|
||||
inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext
|
||||
{
|
||||
NSAssert(self.entityCache, @"Entity cache cannot be nil.");
|
||||
|
||||
if (! [self.entityCache isEntity:entity cachedByAttribute:primaryKeyAttribute]) {
|
||||
RKLogInfo(@"Caching instances of Entity '%@' by primary key attribute '%@'", entity.name, primaryKeyAttribute);
|
||||
[self.entityCache cacheObjectsForEntity:entity byAttribute:primaryKeyAttribute];
|
||||
RKEntityByAttributeCache *attributeCache = [self.entityCache attributeCacheForEntity:entity attribute:primaryKeyAttribute];
|
||||
RKLogTrace(@"Cached %ld objects", (long)[attributeCache count]);
|
||||
}
|
||||
|
||||
return [self.entityCache objectsForEntity:entity withAttribute:primaryKeyAttribute value:primaryKeyValue inContext:managedObjectContext];
|
||||
|
||||
return [self.entityCache objectsForEntity:entity withAttributeValues:attributeValues inContext:managedObjectContext];
|
||||
}
|
||||
|
||||
- (void)didFetchObject:(NSManagedObject *)object
|
||||
|
||||
@@ -18,6 +18,13 @@
|
||||
|
||||
@required
|
||||
|
||||
/// @name Retrieving Managed Objects
|
||||
|
||||
// New API
|
||||
- (NSArray *)managedObjectsWithEntity:(NSEntityDescription *)entity
|
||||
attributeValues:(NSDictionary *)attributeValues
|
||||
inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext;
|
||||
|
||||
///------------------------------
|
||||
/// @name Finding Managed Objects
|
||||
///------------------------------
|
||||
@@ -33,10 +40,10 @@
|
||||
@return A managed object that is an instance of the given entity with a primary key and value matching
|
||||
the specified parameters, or nil if no object was found.
|
||||
*/
|
||||
- (NSManagedObject *)findInstanceOfEntity:(NSEntityDescription *)entity
|
||||
withPrimaryKeyAttribute:(NSString *)primaryKeyAttribute
|
||||
value:(id)primaryKeyValue
|
||||
inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext;
|
||||
//- (NSManagedObject *)findInstanceOfEntity:(NSEntityDescription *)entity
|
||||
// withPrimaryKeyAttribute:(NSString *)primaryKeyAttribute
|
||||
// value:(id)primaryKeyValue
|
||||
// inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext;
|
||||
|
||||
/**
|
||||
Retrieves an array of model objects from the object store given a Core Data entity and
|
||||
@@ -49,10 +56,10 @@
|
||||
@return An array of managed objects that are instances of the given entity with a primary key and value matching
|
||||
the specified parameters, or nil if no object was found.
|
||||
*/
|
||||
- (NSArray *)findInstancesOfEntity:(NSEntityDescription *)entity
|
||||
withPrimaryKeyAttribute:(NSString *)primaryKeyAttribute
|
||||
value:(id)primaryKeyValue
|
||||
inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext;
|
||||
//- (NSArray *)findInstancesOfEntity:(NSEntityDescription *)entity
|
||||
// withPrimaryKeyAttribute:(NSString *)primaryKeyAttribute
|
||||
// value:(id)primaryKeyValue
|
||||
// inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext;
|
||||
|
||||
///---------------------------------------------------
|
||||
/// @name Handling Managed Object Change Notifications
|
||||
|
||||
@@ -26,8 +26,94 @@
|
||||
#import "RKMappingOperation.h"
|
||||
#import "RKDynamicMappingMatcher.h"
|
||||
#import "RKManagedObjectCaching.h"
|
||||
#import "RKRelationshipConnectionOperation.h"
|
||||
#import "RKConnectionOperation.h"
|
||||
#import "RKMappingErrors.h"
|
||||
#import "RKValueTransformers.h"
|
||||
|
||||
extern NSString * const RKObjectMappingNestingAttributeKeyName;
|
||||
|
||||
id RKTransformedValueWithClass(id value, Class destinationType, NSValueTransformer *dateToStringValueTransformer);
|
||||
NSArray *RKApplyNestingAttributeValueToMappings(NSString *attributeName, id value, NSArray *propertyMappings);
|
||||
|
||||
// Return YES if the entity is identified by an attribute that acts as the nesting key in the source representation
|
||||
static BOOL RKEntityMappingIsIdentifiedByNestingAttribute(RKEntityMapping *entityMapping)
|
||||
{
|
||||
for (NSAttributeDescription *attribute in entityMapping.entityIdentifier.attributes) {
|
||||
RKAttributeMapping *attributeMapping = [[entityMapping propertyMappingsByDestinationKeyPath] objectForKey:[attribute name]];
|
||||
if ([attributeMapping.sourceKeyPath isEqualToString:RKObjectMappingNestingAttributeKeyName]) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
// We always need to map the dynamic nesting attribute first so that sub-key attribute mappings apply cleanly
|
||||
static NSArray *RKEntityIdentifierAttributesInMappingOrder(RKEntityMapping *entityMapping)
|
||||
{
|
||||
NSMutableArray *orderedAttributes = [NSMutableArray arrayWithCapacity:[entityMapping.entityIdentifier.attributes count]];
|
||||
for (NSAttributeDescription *attribute in entityMapping.entityIdentifier.attributes) {
|
||||
RKAttributeMapping *attributeMapping = [[entityMapping propertyMappingsByDestinationKeyPath] objectForKey:[attribute name]];
|
||||
if ([attributeMapping.sourceKeyPath isEqualToString:RKObjectMappingNestingAttributeKeyName]) {
|
||||
// We want to map the nesting attribute first
|
||||
[orderedAttributes insertObject:attribute atIndex:0];
|
||||
} else {
|
||||
[orderedAttributes addObject:attribute];
|
||||
}
|
||||
}
|
||||
|
||||
return orderedAttributes;
|
||||
}
|
||||
|
||||
static id RKValueForAttributeMappingInRepresentation(RKAttributeMapping *attributeMapping, NSDictionary *representation)
|
||||
{
|
||||
if ([attributeMapping.sourceKeyPath isEqualToString:RKObjectMappingNestingAttributeKeyName]) {
|
||||
return [[representation allKeys] lastObject];
|
||||
} else {
|
||||
return [representation valueForKeyPath:attributeMapping.sourceKeyPath];
|
||||
}
|
||||
}
|
||||
|
||||
static RKAttributeMapping *RKAttributeMappingForNameInMappings(NSString *name, NSArray *attributeMappings)
|
||||
{
|
||||
for (RKAttributeMapping *attributeMapping in attributeMappings) {
|
||||
if ([[attributeMapping destinationKeyPath] isEqualToString:name]) return attributeMapping;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
/**
|
||||
This function is the workhorse for extracting entity identifier attributes from a dictionary representation. It supports type transformations, compound entity identifier attributes, and dynamic nesting keys within the representation.
|
||||
*/
|
||||
static NSDictionary *RKEntityIdentifierAttributesForEntityMappingWithRepresentation(RKEntityMapping *entityMapping, NSDictionary *representation)
|
||||
{
|
||||
RKDateToStringValueTransformer *dateToStringTransformer = [[RKDateToStringValueTransformer alloc] initWithDateToStringFormatter:entityMapping.preferredDateFormatter
|
||||
stringToDateFormatters:entityMapping.dateFormatters];
|
||||
NSArray *orderedAttributes = RKEntityIdentifierAttributesInMappingOrder(entityMapping);
|
||||
BOOL containsNestingAttribute = RKEntityMappingIsIdentifiedByNestingAttribute(entityMapping);
|
||||
__block NSArray *attributeMappings = entityMapping.attributeMappings;
|
||||
if (containsNestingAttribute) RKLogDebug(@"Detected use of nested dictionary key as identifying attribute");
|
||||
|
||||
NSMutableDictionary *entityIdentifierAttributes = [NSMutableDictionary dictionaryWithCapacity:[orderedAttributes count]];
|
||||
[orderedAttributes enumerateObjectsUsingBlock:^(NSAttributeDescription *attribute, NSUInteger idx, BOOL *stop) {
|
||||
RKAttributeMapping *attributeMapping = RKAttributeMappingForNameInMappings([attribute name], attributeMappings);
|
||||
Class attributeClass = [entityMapping classForProperty:[attribute name]];
|
||||
id attributeValue = nil;
|
||||
if (containsNestingAttribute && idx == 0) {
|
||||
// This is the nesting attribute
|
||||
attributeValue = RKTransformedValueWithClass([[representation allKeys] lastObject], attributeClass, dateToStringTransformer);
|
||||
attributeMappings = RKApplyNestingAttributeValueToMappings([attribute name], attributeValue, attributeMappings);
|
||||
} else {
|
||||
id sourceValue = RKValueForAttributeMappingInRepresentation(attributeMapping, representation);
|
||||
attributeValue = RKTransformedValueWithClass(sourceValue, attributeClass, dateToStringTransformer);
|
||||
}
|
||||
|
||||
[entityIdentifierAttributes setObject:attributeValue ?: [NSNull null] forKey:[attribute name]];
|
||||
}];
|
||||
|
||||
return entityIdentifierAttributes;
|
||||
}
|
||||
|
||||
// Set Logging Component
|
||||
#undef RKLogComponent
|
||||
@@ -64,69 +150,41 @@ extern NSString * const RKObjectMappingNestingAttributeKeyName;
|
||||
return [mapping.objectClass new];
|
||||
}
|
||||
|
||||
RKEntityMapping *entityMapping = (RKEntityMapping *)mapping;
|
||||
id object = nil;
|
||||
id primaryKeyValue = nil;
|
||||
NSString *primaryKeyAttribute;
|
||||
|
||||
NSEntityDescription *entity = [entityMapping entity];
|
||||
RKAttributeMapping *primaryKeyAttributeMapping = nil;
|
||||
|
||||
primaryKeyAttribute = [entityMapping primaryKeyAttribute];
|
||||
if (primaryKeyAttribute) {
|
||||
// If a primary key has been set on the object mapping, find the attribute mapping
|
||||
// so that we can extract any existing primary key from the mappable data
|
||||
for (RKAttributeMapping *attributeMapping in entityMapping.attributeMappings) {
|
||||
if ([attributeMapping.destinationKeyPath isEqualToString:primaryKeyAttribute]) {
|
||||
primaryKeyAttributeMapping = attributeMapping;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the primary key value out of the mappable data (if any)
|
||||
if ([primaryKeyAttributeMapping.sourceKeyPath isEqualToString:RKObjectMappingNestingAttributeKeyName]) {
|
||||
RKLogDebug(@"Detected use of nested dictionary key as primaryKey attribute...");
|
||||
primaryKeyValue = [[representation allKeys] lastObject];
|
||||
} else {
|
||||
NSString* keyPathForPrimaryKeyElement = primaryKeyAttributeMapping.sourceKeyPath;
|
||||
if (keyPathForPrimaryKeyElement) {
|
||||
primaryKeyValue = [representation valueForKeyPath:keyPathForPrimaryKeyElement];
|
||||
} else {
|
||||
RKLogWarning(@"Unable to find source attribute for primaryKeyAttribute '%@': unable to find existing object instances by primary key.", primaryKeyAttribute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RKEntityMapping *entityMapping = (RKEntityMapping *)mapping;
|
||||
NSDictionary *entityIdentifierAttributes = RKEntityIdentifierAttributesForEntityMappingWithRepresentation(entityMapping, representation);
|
||||
if (! self.managedObjectCache) {
|
||||
RKLogWarning(@"Performing managed object mapping with a nil managed object cache:\n"
|
||||
"Unable to update existing object instances by primary key. Duplicate objects may be created.");
|
||||
}
|
||||
|
||||
// If we have found the primary key attribute & value, try to find an existing instance to update
|
||||
if (primaryKeyAttribute && primaryKeyValue && NO == [primaryKeyValue isEqual:[NSNull null]]) {
|
||||
object = [self.managedObjectCache findInstanceOfEntity:entity
|
||||
withPrimaryKeyAttribute:primaryKeyAttribute
|
||||
value:primaryKeyValue
|
||||
inManagedObjectContext:self.managedObjectContext];
|
||||
|
||||
if (object && [self.managedObjectCache respondsToSelector:@selector(didFetchObject:)]) {
|
||||
[self.managedObjectCache didFetchObject:object];
|
||||
// If we have found the entity identifier attributes, try to find an existing instance to update
|
||||
NSEntityDescription *entity = [entityMapping entity];
|
||||
NSManagedObject *managedObject = nil;
|
||||
if ([entityIdentifierAttributes count]) {
|
||||
NSArray *objects = [self.managedObjectCache managedObjectsWithEntity:entity
|
||||
attributeValues:entityIdentifierAttributes
|
||||
inManagedObjectContext:self.managedObjectContext];
|
||||
if (entityMapping.entityIdentifier.predicate) objects = [objects filteredArrayUsingPredicate:entityMapping.entityIdentifier.predicate];
|
||||
if ([objects count] > 0) {
|
||||
managedObject = objects[0];
|
||||
if ([objects count] > 1) RKLogWarning(@"Managed object cache returned %d objects for the identifier configured for the '%@' entity, expected 1.", [objects count], [entity name]);
|
||||
}
|
||||
if (managedObject && [self.managedObjectCache respondsToSelector:@selector(didFetchObject:)]) {
|
||||
[self.managedObjectCache didFetchObject:managedObject];
|
||||
}
|
||||
}
|
||||
|
||||
if (object == nil) {
|
||||
object = [[NSManagedObject alloc] initWithEntity:entity
|
||||
if (managedObject == nil) {
|
||||
managedObject = [[NSManagedObject alloc] initWithEntity:entity
|
||||
insertIntoManagedObjectContext:self.managedObjectContext];
|
||||
if (primaryKeyAttribute && primaryKeyValue && ![primaryKeyValue isEqual:[NSNull null]]) {
|
||||
[object setValue:primaryKeyValue forKey:primaryKeyAttribute];
|
||||
}
|
||||
[managedObject setValuesForKeysWithDictionary:entityIdentifierAttributes];
|
||||
|
||||
if ([self.managedObjectCache respondsToSelector:@selector(didCreateObject:)]) {
|
||||
[self.managedObjectCache didCreateObject:object];
|
||||
[self.managedObjectCache didCreateObject:managedObject];
|
||||
}
|
||||
}
|
||||
|
||||
return object;
|
||||
return managedObject;
|
||||
}
|
||||
|
||||
// Mapping operations should be executed against managed object contexts with the `NSPrivateQueueConcurrencyType` concurrency type
|
||||
@@ -150,27 +208,25 @@ extern NSString * const RKObjectMappingNestingAttributeKeyName;
|
||||
if ([mappingOperation.objectMapping isKindOfClass:[RKEntityMapping class]]) {
|
||||
[self emitDeadlockWarningIfNecessary];
|
||||
|
||||
NSArray *connectionMappings = [(RKEntityMapping *)mappingOperation.objectMapping connectionMappings];
|
||||
if ([connectionMappings count] > 0 && self.managedObjectCache == nil) {
|
||||
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." };
|
||||
NSError *localError = [NSError errorWithDomain:RKErrorDomain code:RKMappingErrorNilManagedObjectCache userInfo:userInfo];
|
||||
if (error) *error = localError;
|
||||
return NO;
|
||||
}
|
||||
|
||||
for (RKConnectionMapping *connectionMapping in connectionMappings) {
|
||||
RKRelationshipConnectionOperation *operation = [[RKRelationshipConnectionOperation alloc] initWithManagedObject:mappingOperation.destinationObject
|
||||
connectionMapping:connectionMapping
|
||||
managedObjectCache:self.managedObjectCache];
|
||||
__weak RKRelationshipConnectionOperation *weakOperation = operation;
|
||||
for (RKConnectionDescription *connection in connections) {
|
||||
RKConnectionOperation *operation = [[RKConnectionOperation alloc] initWithManagedObject:mappingOperation.destinationObject connection:connection managedObjectCache:self.managedObjectCache];
|
||||
__weak RKConnectionOperation *weakOperation = operation;
|
||||
[operation setCompletionBlock:^{
|
||||
if (weakOperation.connectedValue) {
|
||||
if ([mappingOperation.delegate respondsToSelector:@selector(mappingOperation:didConnectRelationship:withValue:usingMapping:)]) {
|
||||
[mappingOperation.delegate mappingOperation:mappingOperation didConnectRelationship:connectionMapping.relationship withValue:weakOperation.connectedValue usingMapping:connectionMapping];
|
||||
[mappingOperation.delegate mappingOperation:mappingOperation didConnectRelationship:connection.relationship toValue:weakOperation.connectedValue usingConnection:connection];
|
||||
}
|
||||
} else {
|
||||
if ([mappingOperation.delegate respondsToSelector:@selector(mappingOperation:didFailToConnectRelationship:usingMapping:)]) {
|
||||
[mappingOperation.delegate mappingOperation:mappingOperation didFailToConnectRelationship:connectionMapping.relationship usingMapping:connectionMapping];
|
||||
[mappingOperation.delegate mappingOperation:mappingOperation didFailToConnectRelationship:connection.relationship usingConnection:connection];
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
@@ -33,8 +33,6 @@
|
||||
#undef RKLogComponent
|
||||
#define RKLogComponent RKlcl_cRestKitNetwork
|
||||
|
||||
id RKTransformValueFromClassToClass(id value, Class sourceType, Class destinationType);
|
||||
|
||||
@interface RKObjectParameterization () <RKMappingOperationDelegate>
|
||||
@property (nonatomic, strong) id object;
|
||||
@property (nonatomic, strong) RKRequestDescriptor *requestDescriptor;
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#import "RKObjectMapping.h"
|
||||
#import "RKAttributeMapping.h"
|
||||
|
||||
@class RKMappingOperation, RKDynamicMapping, RKConnectionMapping;
|
||||
@class RKMappingOperation, RKDynamicMapping, RKConnectionDescription;
|
||||
@protocol RKMappingOperationDataSource;
|
||||
|
||||
/**
|
||||
@@ -99,9 +99,9 @@
|
||||
@param operation The mapping operation.
|
||||
@param relationship The relationship that was connected.
|
||||
@param value The value that was connected to the relationship
|
||||
@param connectionMapping The mappings that was used to connect the relationship.
|
||||
@param connection The connection object describing how the relationship was to be connected.
|
||||
*/
|
||||
- (void)mappingOperation:(RKMappingOperation *)operation didConnectRelationship:(NSRelationshipDescription *)relationship withValue:(id)value usingMapping:(RKConnectionMapping *)connectionMapping;
|
||||
- (void)mappingOperation:(RKMappingOperation *)operation didConnectRelationship:(NSRelationshipDescription *)relationship toValue:(id)value usingConnection:(RKConnectionDescription *)connection;
|
||||
|
||||
/**
|
||||
Tells the delegate that the mapping operation failed to connect a relationship.
|
||||
@@ -110,9 +110,9 @@
|
||||
|
||||
@param operation The mapping operation.
|
||||
@param relationship The relationship that was connected.
|
||||
@param connectionMapping The mappings that was used to connect the relationship.
|
||||
@param connection The connection object describing how the relationship was to be connected.
|
||||
*/
|
||||
- (void)mappingOperation:(RKMappingOperation *)operation didFailToConnectRelationship:(NSRelationshipDescription *)relationship usingMapping:(RKConnectionMapping *)connectionMapping;
|
||||
- (void)mappingOperation:(RKMappingOperation *)operation didFailToConnectRelationship:(NSRelationshipDescription *)relationship usingConnection:(RKConnectionDescription *)connection;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#import "RKObjectMappingOperationDataSource.h"
|
||||
#import "RKDynamicMapping.h"
|
||||
#import "RKObjectUtilities.h"
|
||||
#import "RKValueTransformers.h"
|
||||
|
||||
// Set Logging Component
|
||||
#undef RKLogComponent
|
||||
@@ -62,10 +63,22 @@ static BOOL RKIsManagedObject(id object)
|
||||
return managedObjectClass && [object isKindOfClass:managedObjectClass];
|
||||
}
|
||||
|
||||
id RKTransformValueFromClassToClass(id value, Class sourceType, Class destinationType);
|
||||
id RKTransformValueFromClassToClass(id value, Class sourceType, Class destinationType)
|
||||
id RKTransformedValueWithClass(id value, Class destinationType, NSValueTransformer *dateToStringValueTransformer);
|
||||
id RKTransformedValueWithClass(id value, Class destinationType, NSValueTransformer *dateToStringValueTransformer)
|
||||
{
|
||||
if ([destinationType isSubclassOfClass:[NSData class]]) {
|
||||
Class sourceType = [value class];
|
||||
|
||||
if ([value isKindOfClass:destinationType]) {
|
||||
// No transformation necessary
|
||||
return value;
|
||||
} else if ([sourceType isSubclassOfClass:[NSString class]] && [destinationType isSubclassOfClass:[NSDate class]]) {
|
||||
// String -> Date
|
||||
return [dateToStringValueTransformer transformedValue:value];
|
||||
} else if ([destinationType isSubclassOfClass:[NSString class]] && [value isKindOfClass:[NSDate class]]) {
|
||||
// NSDate -> NSString
|
||||
// Transform using the preferred date formatter
|
||||
return [dateToStringValueTransformer reverseTransformedValue:value];
|
||||
} else if ([destinationType isSubclassOfClass:[NSData class]]) {
|
||||
return [NSKeyedArchiver archivedDataWithRootObject:value];
|
||||
} else if ([sourceType isSubclassOfClass:[NSString class]]) {
|
||||
if ([destinationType isSubclassOfClass:[NSURL class]]) {
|
||||
@@ -135,6 +148,33 @@ id RKTransformValueFromClassToClass(id value, Class sourceType, Class destinatio
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Applies
|
||||
// Key comes from: [[_nestedAttributeSubstitution allKeys] lastObject]] AND [[_nestedAttributeSubstitution allValues] lastObject];
|
||||
NSArray *RKApplyNestingAttributeValueToMappings(NSString *attributeName, id value, NSArray *propertyMappings);
|
||||
NSArray *RKApplyNestingAttributeValueToMappings(NSString *attributeName, id value, NSArray *propertyMappings)
|
||||
{
|
||||
if (!attributeName) return propertyMappings;
|
||||
|
||||
NSString *searchString = [NSString stringWithFormat:@"(%@)", attributeName];
|
||||
NSString *replacementString = [NSString stringWithFormat:@"%@", value];
|
||||
NSMutableArray *nestedMappings = [NSMutableArray arrayWithCapacity:[propertyMappings count]];
|
||||
for (RKPropertyMapping *propertyMapping in propertyMappings) {
|
||||
NSString *sourceKeyPath = [propertyMapping.sourceKeyPath stringByReplacingOccurrencesOfString:searchString withString:replacementString];
|
||||
NSString *destinationKeyPath = [propertyMapping.destinationKeyPath stringByReplacingOccurrencesOfString:searchString withString:replacementString];
|
||||
RKPropertyMapping *nestedMapping = nil;
|
||||
if ([propertyMapping isKindOfClass:[RKAttributeMapping class]]) {
|
||||
nestedMapping = [RKAttributeMapping attributeMappingFromKeyPath:sourceKeyPath toKeyPath:destinationKeyPath];
|
||||
} else if ([propertyMapping isKindOfClass:[RKRelationshipMapping class]]) {
|
||||
nestedMapping = [RKRelationshipMapping relationshipMappingFromKeyPath:sourceKeyPath
|
||||
toKeyPath:destinationKeyPath
|
||||
withMapping:[(RKRelationshipMapping *)propertyMapping mapping]];
|
||||
}
|
||||
[nestedMappings addObject:nestedMapping];
|
||||
}
|
||||
|
||||
return nestedMappings;
|
||||
}
|
||||
|
||||
@interface RKMappingOperation ()
|
||||
@property (nonatomic, strong, readwrite) RKMapping *mapping;
|
||||
@property (nonatomic, strong, readwrite) id sourceObject;
|
||||
@@ -186,23 +226,9 @@ id RKTransformValueFromClassToClass(id value, Class sourceType, Class destinatio
|
||||
- (id)transformValue:(id)value atKeyPath:(NSString *)keyPath toType:(Class)destinationType
|
||||
{
|
||||
RKLogTrace(@"Found transformable value at keyPath '%@'. Transforming from type '%@' to '%@'", keyPath, NSStringFromClass([value class]), NSStringFromClass(destinationType));
|
||||
Class sourceType = [value class];
|
||||
|
||||
if ([sourceType isSubclassOfClass:[NSString class]] && [destinationType isSubclassOfClass:[NSDate class]]) {
|
||||
// String -> Date
|
||||
return [self parseDateFromString:(NSString *)value];
|
||||
} else if ([destinationType isSubclassOfClass:[NSString class]] && [value isKindOfClass:[NSDate class]]) {
|
||||
// NSDate -> NSString
|
||||
// Transform using the preferred date formatter
|
||||
NSString *dateString = nil;
|
||||
@synchronized(self.objectMapping.preferredDateFormatter) {
|
||||
dateString = [self.objectMapping.preferredDateFormatter stringForObjectValue:value];
|
||||
}
|
||||
return dateString;
|
||||
} else {
|
||||
id transformedValue = RKTransformValueFromClassToClass(value, sourceType, destinationType);
|
||||
if (transformedValue != value) return transformedValue;
|
||||
}
|
||||
RKDateToStringValueTransformer *transformer = [[RKDateToStringValueTransformer alloc] initWithDateToStringFormatter:self.objectMapping.preferredDateFormatter stringToDateFormatters:self.objectMapping.dateFormatters];
|
||||
id transformedValue = RKTransformedValueWithClass(value, destinationType, transformer);
|
||||
if (transformedValue != value) return transformedValue;
|
||||
|
||||
RKLogWarning(@"Failed transformation of value at keyPath '%@'. No strategy for transforming from '%@' to '%@'", keyPath, NSStringFromClass([value class]), NSStringFromClass(destinationType));
|
||||
|
||||
@@ -269,27 +295,30 @@ id RKTransformValueFromClassToClass(id value, Class sourceType, Class destinatio
|
||||
return NO;
|
||||
}
|
||||
|
||||
// TODO:
|
||||
- (NSArray *)applyNestingToMappings:(NSArray *)mappings
|
||||
{
|
||||
if (_nestedAttributeSubstitution) {
|
||||
NSString *searchString = [NSString stringWithFormat:@"(%@)", [[_nestedAttributeSubstitution allKeys] lastObject]];
|
||||
NSString *replacementString = [[_nestedAttributeSubstitution allValues] lastObject];
|
||||
NSMutableArray *array = [NSMutableArray arrayWithCapacity:[self.objectMapping.attributeMappings count]];
|
||||
for (RKPropertyMapping *mapping in mappings) {
|
||||
NSString *sourceKeyPath = [mapping.sourceKeyPath stringByReplacingOccurrencesOfString:searchString withString:replacementString];
|
||||
NSString *destinationKeyPath = [mapping.destinationKeyPath stringByReplacingOccurrencesOfString:searchString withString:replacementString];
|
||||
RKPropertyMapping *nestedMapping = nil;
|
||||
if ([mapping isKindOfClass:[RKAttributeMapping class]]) {
|
||||
nestedMapping = [RKAttributeMapping attributeMappingFromKeyPath:sourceKeyPath toKeyPath:mapping.destinationKeyPath];
|
||||
} else if ([mapping isKindOfClass:[RKRelationshipMapping class]]) {
|
||||
nestedMapping = [RKRelationshipMapping relationshipMappingFromKeyPath:sourceKeyPath
|
||||
toKeyPath:destinationKeyPath
|
||||
withMapping:[(RKRelationshipMapping *)mapping mapping]];
|
||||
}
|
||||
[array addObject:nestedMapping];
|
||||
}
|
||||
|
||||
return array;
|
||||
return RKApplyNestingAttributeValueToMappings([[_nestedAttributeSubstitution allKeys] lastObject], [[_nestedAttributeSubstitution allValues] lastObject], mappings);
|
||||
|
||||
// NSString *searchString = [NSString stringWithFormat:@"(%@)", [[_nestedAttributeSubstitution allKeys] lastObject]];
|
||||
// NSString *replacementString = [[_nestedAttributeSubstitution allValues] lastObject];
|
||||
// NSMutableArray *array = [NSMutableArray arrayWithCapacity:[self.objectMapping.attributeMappings count]];
|
||||
// for (RKPropertyMapping *mapping in mappings) {
|
||||
// NSString *sourceKeyPath = [mapping.sourceKeyPath stringByReplacingOccurrencesOfString:searchString withString:replacementString];
|
||||
// NSString *destinationKeyPath = [mapping.destinationKeyPath stringByReplacingOccurrencesOfString:searchString withString:replacementString];
|
||||
// RKPropertyMapping *nestedMapping = nil;
|
||||
// if ([mapping isKindOfClass:[RKAttributeMapping class]]) {
|
||||
// nestedMapping = [RKAttributeMapping attributeMappingFromKeyPath:sourceKeyPath toKeyPath:mapping.destinationKeyPath];
|
||||
// } else if ([mapping isKindOfClass:[RKRelationshipMapping class]]) {
|
||||
// nestedMapping = [RKRelationshipMapping relationshipMappingFromKeyPath:sourceKeyPath
|
||||
// toKeyPath:destinationKeyPath
|
||||
// withMapping:[(RKRelationshipMapping *)mapping mapping]];
|
||||
// }
|
||||
// [array addObject:nestedMapping];
|
||||
// }
|
||||
//
|
||||
// return array;
|
||||
}
|
||||
|
||||
return mappings;
|
||||
@@ -391,7 +420,7 @@ id RKTransformValueFromClassToClass(id value, Class sourceType, Class destinatio
|
||||
|
||||
// Optionally set the default value for missing values
|
||||
if ([self.objectMapping shouldSetDefaultValueForMissingAttributes]) {
|
||||
[self.destinationObject setValue:[self.objectMapping defaultValueForMissingAttribute:attributeMapping.destinationKeyPath]
|
||||
[self.destinationObject setValue:[self.objectMapping defaultValueForAttribute:attributeMapping.destinationKeyPath]
|
||||
forKeyPath:attributeMapping.destinationKeyPath];
|
||||
RKLogTrace(@"Setting nil for missing attribute value at keyPath '%@'", attributeMapping.sourceKeyPath);
|
||||
}
|
||||
@@ -611,7 +640,7 @@ id RKTransformValueFromClassToClass(id value, Class sourceType, Class destinatio
|
||||
|
||||
- (void)applyNestedMappings
|
||||
{
|
||||
RKAttributeMapping *attributeMapping = [self.objectMapping attributeMappingForKeyOfNestedDictionary];
|
||||
RKAttributeMapping *attributeMapping = [self.objectMapping attributeMappingForKeyOfRepresentation];
|
||||
if (attributeMapping) {
|
||||
RKLogDebug(@"Found nested mapping definition to attribute '%@'", attributeMapping.destinationKeyPath);
|
||||
id attributeValue = [[self.sourceObject allKeys] lastObject];
|
||||
|
||||
@@ -26,11 +26,10 @@
|
||||
/**
|
||||
An `RKObjectMapping` object describes a transformation between object represenations using key-value coding and run-time type introspection. The mapping is defined in terms of a source object class and a collection of `RKPropertyMapping` objects describing how key paths in the source representation should be transformed into attributes and relationships on the target object. Object mappings are provided to instances of `RKMapperOperation` and `RKMappingOperation` to perform the transformations they describe.
|
||||
|
||||
Object mappings are containers of property mappings that describe the actual key path transformations. There are three types of property mappings:
|
||||
Object mappings are containers of property mappings that describe the actual key path transformations. There are two types of property mappings:
|
||||
|
||||
1. `RKAttributeMapping`: An attribute mapping describes a transformation between a single value from a source key path to a destination key path. The value to be mapped is read from the source object representation using `valueForKeyPath:` and then set to the destination key path using `setValueForKeyPath:`. Before the value is set, the `RKObjecMappingOperation` performing the mapping performs runtime introspection on the destination property to determine what, if any, type transformation is to be performed. Typical type transformations include reading an `NSString` value representation and mapping it to an `NSDecimalNumber` destination key path or reading an `NSString` and transforming it into an `NSDate` value before assigning to the destination.
|
||||
1. `RKRelationshipMapping`: A relationship mapping describes a transformation between a nested child object or objects from a source key path to a destination key path using another `RKObjectMapping`. The child objects to be mapped are read from the source object representation using `valueForKeyPath:`, then mapped recursively using the object mapping associated with the relationship mapping, and then finally assigned to the destination key path. Before assignment to the destination key path runtime type introspection is performed to determine if any type transformation is necessary. For relationship mappings, common type transformations include transforming a single object value in an `NSArray` or transforming an `NSArray` of object values into an `NSSet`.
|
||||
1. `RKConnectionMapping`: A connection mapping describes how to establish a relationship within a Core Data data model using foreign keys transmitted within the mapped response body.
|
||||
|
||||
All type transformations available are discussed in detail in the documentation for `RKMappingOperation`.
|
||||
|
||||
@@ -170,7 +169,10 @@
|
||||
/**
|
||||
Adds a relationship mapping to the receiver with the given source key path and mapping.
|
||||
|
||||
The
|
||||
The destination key path will be the same as the source key path or processed by the source to destination key transformation block, if any is configured.
|
||||
|
||||
@param sourceKeyPath The source key path at which to read the nested representation of the related objects.
|
||||
@param mapping The object mapping with which to process the related object representation.
|
||||
*/
|
||||
- (void)addRelationshipMappingWithSourceKeyPath:(NSString *)sourceKeyPath mapping:(RKMapping *)mapping;
|
||||
|
||||
@@ -184,7 +186,7 @@
|
||||
@param block The block to be set as the default source to destination key transformer for all object mappings in the application.
|
||||
@see [RKObjectMapping setPropertyNameTransformationBlock:]
|
||||
*/
|
||||
+ (void)setDefaultSourceToDestinationKeyTransformationBlock:(NSString * (^)(NSString *sourceKey))block;
|
||||
+ (void)setDefaultSourceToDestinationKeyTransformationBlock:(NSString * (^)(RKObjectMapping *mapping, NSString *sourceKey))block;
|
||||
|
||||
/**
|
||||
Sets a block to executed to transform a source key into a destination key.
|
||||
@@ -196,14 +198,14 @@
|
||||
@param block The block to execute when the receiver needs to transform a source key into a destination key. The block has a string return value specifying the destination key and accepts a single string argument: the source key that is to be transformed.
|
||||
@warning Please note that the block given accepts a **key** as opposed to a **key path**. When a key path is given to a method supporting key transformation it will be decomposed into its key components by splitting the key path at the '.' (period) character, then each key will be evaluated using the transformation block and the results will be joined together into a new key path with the period character delimiter.
|
||||
*/
|
||||
- (void)setSourceToDestinationKeyTransformationBlock:(NSString * (^)(NSString *sourceKey))block;
|
||||
- (void)setSourceToDestinationKeyTransformationBlock:(NSString * (^)(RKObjectMapping *mapping, NSString *sourceKey))block;
|
||||
|
||||
///----------------------------------
|
||||
/// @name Mapping Nested Dictionaries
|
||||
///----------------------------------
|
||||
|
||||
/**
|
||||
Configures a sub-key mapping for cases where JSON has been nested underneath a key named after an attribute.
|
||||
Adds an attribute mapping from a dynamic nesting key value to an attribute. The mapped attribute name can then be referenced within other attribute mappings to access the nested content.
|
||||
|
||||
For example, consider the following JSON:
|
||||
|
||||
@@ -218,15 +220,10 @@
|
||||
|
||||
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[User class]];
|
||||
mapping.forceCollectionMapping = YES; // RestKit cannot infer this is a collection, so we force it
|
||||
[mapping mapKeyOfNestedDictionaryToAttribute:@"firstName"];
|
||||
[mapping mapFromKeyPath:@"(firstName).id" toAttribute:"userID"];
|
||||
[mapping mapFromKeyPath:@"(firstName).email" toAttribute:"email"];
|
||||
|
||||
[[RKObjectManager sharedManager].mappingProvider setObjectMapping:mapping forKeyPath:@"users"];
|
||||
|
||||
[mapping addAttributeMappingFromKeyOfRepresentationToAttribute:@"firstName"];
|
||||
[mapping addAttributeMappingsFromDictionary:@{ @"(firstName).id": @"userID", @"(firstName).email": @"email" }];
|
||||
*/
|
||||
- (void)mapKeyOfNestedDictionaryToAttribute:(NSString *)attributeName;
|
||||
// TODO: Can we eliminate this API???
|
||||
- (void)addAttributeMappingFromKeyOfRepresentationToAttribute:(NSString *)attributeName;
|
||||
|
||||
/**
|
||||
Returns the attribute mapping targeting the key of a nested dictionary in the source JSON.
|
||||
@@ -234,9 +231,9 @@
|
||||
This attribute mapping corresponds to the attributeName configured via `mapKeyOfNestedDictionaryToAttribute:`
|
||||
|
||||
@return An attribute mapping for the key of a nested dictionary being mapped or nil
|
||||
@see `mapKeyOfNestedDictionaryToAttribute:`
|
||||
@see `addAttributeMappingFromKeyOfRepresentationToAttribute:`
|
||||
*/
|
||||
- (RKAttributeMapping *)attributeMappingForKeyOfNestedDictionary;
|
||||
- (RKAttributeMapping *)attributeMappingForKeyOfRepresentation;
|
||||
|
||||
///----------------------------------
|
||||
/// @name Configuring Mapping Options
|
||||
@@ -270,9 +267,9 @@
|
||||
|
||||
The default implementation returns nil for transient object mappings. On an entity mapping, the default value returned from the Entity definition will be used.
|
||||
|
||||
@see `[RKEntityMapping defaultValueForMissingAttribute:]`
|
||||
@see `[RKEntityMapping defaultValueForAttribute:]`
|
||||
*/
|
||||
- (id)defaultValueForMissingAttribute:(NSString *)attributeName;
|
||||
- (id)defaultValueForAttribute:(NSString *)attributeName;
|
||||
|
||||
///----------------------------------
|
||||
/// @name Configuring Date Formatters
|
||||
@@ -302,7 +299,6 @@
|
||||
mapping will have the source and destination keyPaths swapped for all attribute and relationship mappings.
|
||||
*/
|
||||
- (RKObjectMapping *)inverseMapping;
|
||||
// TODO: Keep or kill inverse???
|
||||
|
||||
///---------------------------------------------------
|
||||
/// @name Obtaining Information About the Target Class
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#import "RKAttributeMapping.h"
|
||||
#import "RKRelationshipMapping.h"
|
||||
|
||||
typedef NSString * (^RKSourceToDesinationKeyTransformationBlock)(RKObjectMapping *, NSString *sourceKey);
|
||||
|
||||
// Constants
|
||||
NSString * const RKObjectMappingNestingAttributeKeyName = @"<RK_NESTING_ATTRIBUTE>";
|
||||
static NSUInteger RKObjectMappingMaximumInverseMappingRecursionDepth = 100;
|
||||
@@ -33,22 +35,8 @@ static NSUInteger RKObjectMappingMaximumInverseMappingRecursionDepth = 100;
|
||||
// Private declaration
|
||||
NSDate *RKDateFromStringWithFormatters(NSString *dateString, NSArray *formatters);
|
||||
|
||||
typedef NSString * (^RKSourceToDesinationKeyTransformationBlock)(NSString *sourceKey);
|
||||
|
||||
static RKSourceToDesinationKeyTransformationBlock defaultSourceToDestinationKeyTransformationBlock = nil;
|
||||
|
||||
// Evaluate each component individually so that camelization, etc. considers each component individually
|
||||
static NSString *RKDestinationKeyPathFromTransformationBlockWithSourceKeyPath(RKSourceToDesinationKeyTransformationBlock block, NSString *keyPath)
|
||||
{
|
||||
NSArray *components = [keyPath componentsSeparatedByString:@"."];
|
||||
NSMutableArray *mutableComponents = [NSMutableArray arrayWithCapacity:[components count]];
|
||||
[components enumerateObjectsUsingBlock:^(id component, NSUInteger idx, BOOL *stop) {
|
||||
[mutableComponents addObject:block(component)];
|
||||
}];
|
||||
|
||||
return [mutableComponents componentsJoinedByString:@"."];
|
||||
}
|
||||
|
||||
@interface RKPropertyMapping ()
|
||||
@property (nonatomic, weak, readwrite) RKObjectMapping *objectMapping;
|
||||
@end
|
||||
@@ -109,7 +97,7 @@ static NSString *RKDestinationKeyPathFromTransformationBlockWithSourceKeyPath(RK
|
||||
return copy;
|
||||
}
|
||||
|
||||
+ (void)setDefaultSourceToDestinationKeyTransformationBlock:(NSString * (^)(NSString *sourceKey))block
|
||||
+ (void)setDefaultSourceToDestinationKeyTransformationBlock:(RKSourceToDesinationKeyTransformationBlock)block
|
||||
{
|
||||
defaultSourceToDestinationKeyTransformationBlock = block;
|
||||
}
|
||||
@@ -219,6 +207,20 @@ static NSString *RKDestinationKeyPathFromTransformationBlockWithSourceKeyPath(RK
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Evaluate each component individually so that camelization, etc. considers each component individually
|
||||
- (NSString *)transformSourceKeyPath:(NSString *)keyPath
|
||||
{
|
||||
if (!self.sourceToDestinationKeyTransformationBlock) return keyPath;
|
||||
|
||||
NSArray *components = [keyPath componentsSeparatedByString:@"."];
|
||||
NSMutableArray *mutableComponents = [NSMutableArray arrayWithCapacity:[components count]];
|
||||
[components enumerateObjectsUsingBlock:^(id component, NSUInteger idx, BOOL *stop) {
|
||||
[mutableComponents addObject:self.sourceToDestinationKeyTransformationBlock(self, component)];
|
||||
}];
|
||||
|
||||
return [mutableComponents componentsJoinedByString:@"."];
|
||||
}
|
||||
|
||||
- (void)addAttributeMappingsFromDictionary:(NSDictionary *)keyPathToAttributeNames
|
||||
{
|
||||
for (NSString *attributeKeyPath in keyPathToAttributeNames) {
|
||||
@@ -231,7 +233,7 @@ static NSString *RKDestinationKeyPathFromTransformationBlockWithSourceKeyPath(RK
|
||||
NSMutableArray *arrayOfAttributeMappings = [NSMutableArray arrayWithCapacity:[arrayOfAttributeNamesOrMappings count]];
|
||||
for (id entry in arrayOfAttributeNamesOrMappings) {
|
||||
if ([entry isKindOfClass:[NSString class]]) {
|
||||
NSString *destinationKeyPath = self.sourceToDestinationKeyTransformationBlock ? RKDestinationKeyPathFromTransformationBlockWithSourceKeyPath(self.sourceToDestinationKeyTransformationBlock, entry) : entry;
|
||||
NSString *destinationKeyPath = [self transformSourceKeyPath:entry];
|
||||
[arrayOfAttributeMappings addObject:[RKAttributeMapping attributeMappingFromKeyPath:entry toKeyPath:destinationKeyPath]];
|
||||
} else if ([entry isKindOfClass:[RKAttributeMapping class]]) {
|
||||
[arrayOfAttributeMappings addObject:entry];
|
||||
@@ -249,7 +251,7 @@ static NSString *RKDestinationKeyPathFromTransformationBlockWithSourceKeyPath(RK
|
||||
NSParameterAssert(sourceKeyPath);
|
||||
NSParameterAssert(mapping);
|
||||
|
||||
NSString *destinationKeyPath = self.sourceToDestinationKeyTransformationBlock ? RKDestinationKeyPathFromTransformationBlockWithSourceKeyPath(self.sourceToDestinationKeyTransformationBlock, sourceKeyPath) : sourceKeyPath;
|
||||
NSString *destinationKeyPath = [self transformSourceKeyPath:sourceKeyPath];
|
||||
RKRelationshipMapping *relationshipMapping = [RKRelationshipMapping relationshipMappingFromKeyPath:sourceKeyPath toKeyPath:destinationKeyPath withMapping:mapping];
|
||||
[self addPropertyMapping:relationshipMapping];
|
||||
}
|
||||
@@ -287,12 +289,12 @@ static NSString *RKDestinationKeyPathFromTransformationBlockWithSourceKeyPath(RK
|
||||
return [self inverseMappingAtDepth:0];
|
||||
}
|
||||
|
||||
- (void)mapKeyOfNestedDictionaryToAttribute:(NSString *)attributeName
|
||||
- (void)addAttributeMappingFromKeyOfRepresentationToAttribute:(NSString *)attributeName
|
||||
{
|
||||
[self addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:RKObjectMappingNestingAttributeKeyName toKeyPath:attributeName]];
|
||||
}
|
||||
|
||||
- (RKAttributeMapping *)attributeMappingForKeyOfNestedDictionary
|
||||
- (RKAttributeMapping *)attributeMappingForKeyOfRepresentation
|
||||
{
|
||||
return [self mappingForKeyPath:RKObjectMappingNestingAttributeKeyName];
|
||||
}
|
||||
@@ -319,7 +321,7 @@ static NSString *RKDestinationKeyPathFromTransformationBlockWithSourceKeyPath(RK
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (id)defaultValueForMissingAttribute:(NSString *)attributeName
|
||||
- (id)defaultValueForAttribute:(NSString *)attributeName
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
18
Code/ObjectMapping/RKValueTransformers.h
Normal file
18
Code/ObjectMapping/RKValueTransformers.h
Normal file
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// RKValueTransformers.h
|
||||
// RestKit
|
||||
//
|
||||
// Created by Blake Watters on 11/26/12.
|
||||
// Copyright (c) 2012 RestKit. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface RKDateToStringValueTransformer : NSValueTransformer
|
||||
|
||||
@property (nonatomic, copy) NSFormatter *dateToStringFormatter;
|
||||
@property (nonatomic, copy) NSArray *stringToDateFormatters;
|
||||
|
||||
- (id)initWithDateToStringFormatter:(NSFormatter *)dateToStringFormatter stringToDateFormatters:(NSArray *)stringToDateFormatters;
|
||||
|
||||
@end
|
||||
53
Code/ObjectMapping/RKValueTransformers.m
Normal file
53
Code/ObjectMapping/RKValueTransformers.m
Normal file
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// RKValueTransformers.m
|
||||
// RestKit
|
||||
//
|
||||
// Created by Blake Watters on 11/26/12.
|
||||
// Copyright (c) 2012 RestKit. All rights reserved.
|
||||
//
|
||||
|
||||
#import "RKValueTransformers.h"
|
||||
#import "RKMacros.h"
|
||||
|
||||
// Implementation lives in RKObjectMapping.m at the moment
|
||||
NSDate *RKDateFromStringWithFormatters(NSString *dateString, NSArray *formatters);
|
||||
|
||||
@implementation RKDateToStringValueTransformer
|
||||
|
||||
+ (Class)transformedValueClass
|
||||
{
|
||||
return [NSDate class];
|
||||
}
|
||||
|
||||
+ (BOOL)allowsReverseTransformation
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (id)initWithDateToStringFormatter:(NSFormatter *)dateToStringFormatter stringToDateFormatters:(NSArray *)stringToDateFormatters
|
||||
{
|
||||
self = [self init];
|
||||
if (self) {
|
||||
self.dateToStringFormatter = dateToStringFormatter;
|
||||
self.stringToDateFormatters = stringToDateFormatters;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)transformedValue:(id)value
|
||||
{
|
||||
NSAssert(self.stringToDateFormatters, @"Cannot transform an `NSDate` to an `NSString`: stringToDateFormatters is nil");
|
||||
RKAssertValueIsKindOfClass(value, [NSString class]);
|
||||
return RKDateFromStringWithFormatters(value, self.stringToDateFormatters);
|
||||
}
|
||||
|
||||
- (id)reverseTransformedValue:(id)value
|
||||
{
|
||||
NSAssert(self.dateToStringFormatter, @"Cannot transform an `NSDate` to an `NSString`: dateToStringFormatter is nil");
|
||||
RKAssertValueIsKindOfClass(value, [NSDate class]);
|
||||
@synchronized(self.dateToStringFormatter) {
|
||||
return [self.dateToStringFormatter stringForObjectValue:value];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -40,4 +40,12 @@
|
||||
#define RK_FIX_CATEGORY_BUG(name) @interface RK_FIX_CATEGORY_BUG##name @end \
|
||||
@implementation RK_FIX_CATEGORY_BUG##name @end
|
||||
|
||||
/*
|
||||
Raises an `NSInvalidArgumentException` in the event that the given value is not an instance of the given class or an instance of any class that inherits from that class.
|
||||
*/
|
||||
#define RKAssertValueIsKindOfClass(value, expectedClass) \
|
||||
if (! [value isKindOfClass:expectedClass]) { \
|
||||
[NSException raise:NSInvalidArgumentException format:@"%@ invoked with invalid input value: expected a `%@`, but instead got a `%@`", [self class], expectedClass, [value class]]; \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -90,23 +90,6 @@
|
||||
/// @name Creating Paths from Objects
|
||||
///----------------------------------
|
||||
|
||||
/**
|
||||
Generates a new path by interpolating the properties of the 'object' argument, assuming the existence of a previously specified pattern established via `pathMatcherWithPattern:`. Otherwise, this method is identical in function to `RKPathFromPatternWithObject` (in fact it is a shortcut for this method).
|
||||
|
||||
For example, given an 'article' object with an 'articleID' property value of 12345 ...
|
||||
|
||||
RKPathMatcher *matcher = [RKPathMatcher pathMatcherWithPattern:@"/articles/:articleID"];
|
||||
NSString *path = [matcher pathFromObject:article];
|
||||
|
||||
... will produce a 'path' containing the string "/articles/12345"
|
||||
|
||||
@param object The object containing the properties to interpolate.
|
||||
@return A string with the object's interpolated property values inserted into the receiver's established pattern.
|
||||
@see `RKPathFromPatternWithObject`
|
||||
@see `RKRouter`
|
||||
*/
|
||||
- (NSString *)pathFromObject:(id)object DEPRECATED_ATTRIBUTE;
|
||||
|
||||
/**
|
||||
Generates a path by interpolating the properties of the 'object' argument, assuming the existence of a previously specified pattern established via `pathMatcherWithPattern:`. Otherwise, this method is identical in function to `RKPathFromPatternWithObject` (in fact it is a shortcut for this method).
|
||||
|
||||
|
||||
@@ -128,11 +128,6 @@ static NSString *RKEncodeURLString(NSString *unencodedString)
|
||||
return [self itMatchesAndHasParsedArguments:arguments tokenizeQueryStrings:shouldTokenize];
|
||||
}
|
||||
|
||||
- (NSString *)pathFromObject:(id)object
|
||||
{
|
||||
return [self pathFromObject:object addingEscapes:YES];
|
||||
}
|
||||
|
||||
- (NSString *)pathFromObject:(id)object addingEscapes:(BOOL)addEscapes
|
||||
{
|
||||
NSAssert(self.socPattern != NULL, @"Matcher has no established pattern. Instantiate it using pathMatcherWithPattern: before calling pathFromObject:");
|
||||
|
||||
@@ -43,18 +43,21 @@ NSString * const RKMappingTestVerificationFailureException = @"RKMappingTestVeri
|
||||
@interface RKMappingTestEvent : NSObject
|
||||
|
||||
@property (nonatomic, strong, readonly) RKPropertyMapping *propertyMapping;
|
||||
@property (nonatomic, strong, readonly) RKConnectionDescription *connection;
|
||||
@property (nonatomic, strong, readonly) id value;
|
||||
|
||||
@property (weak, nonatomic, readonly) NSString *sourceKeyPath;
|
||||
@property (weak, nonatomic, readonly) NSString *destinationKeyPath;
|
||||
|
||||
+ (RKMappingTestEvent *)eventWithMapping:(RKPropertyMapping *)propertyMapping value:(id)value;
|
||||
+ (RKMappingTestEvent *)eventWithConnection:(RKConnectionDescription *)connection value:(id)value;
|
||||
|
||||
@end
|
||||
|
||||
@interface RKMappingTestEvent ()
|
||||
@property (nonatomic, strong, readwrite) id value;
|
||||
@property (nonatomic, strong, readwrite) RKPropertyMapping *propertyMapping;
|
||||
@property (nonatomic, strong, readwrite) RKConnectionDescription *connection;
|
||||
@end
|
||||
|
||||
@implementation RKMappingTestEvent
|
||||
@@ -68,6 +71,14 @@ NSString * const RKMappingTestVerificationFailureException = @"RKMappingTestVeri
|
||||
return event;
|
||||
}
|
||||
|
||||
+ (RKMappingTestEvent *)eventWithConnection:(RKConnectionDescription *)connection value:(id)value
|
||||
{
|
||||
RKMappingTestEvent *event = [RKMappingTestEvent new];
|
||||
event.connection = connection;
|
||||
event.value = value;
|
||||
return event;
|
||||
}
|
||||
|
||||
- (NSString *)sourceKeyPath
|
||||
{
|
||||
return [self.propertyMapping sourceKeyPath];
|
||||
@@ -80,8 +91,20 @@ NSString * const RKMappingTestVerificationFailureException = @"RKMappingTestVeri
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"%@ mapped sourceKeyPath '%@' => destinationKeyPath '%@' with value: %@>", [self class],
|
||||
self.sourceKeyPath, self.destinationKeyPath, self.value];
|
||||
if (self.propertyMapping) {
|
||||
return [NSString stringWithFormat:@"%@ mapped sourceKeyPath '%@' => destinationKeyPath '%@' with value: %@>", [self class],
|
||||
self.sourceKeyPath, self.destinationKeyPath, self.value];
|
||||
} else if (self.connection) {
|
||||
if ([self.connection isForeignKeyConnection]) {
|
||||
return [NSString stringWithFormat:@"%@ connected Relationship '%@' using attributes '%@' to value: %@>", [self class],
|
||||
[self.connection.relationship name], [self.connection.attributes valueForKey:@"name"], self.value];
|
||||
} else if ([self.connection isKeyPathConnection]) {
|
||||
return [NSString stringWithFormat:@"%@ connected Relationship '%@' using keyPath '%@' to value: %@>", [self class],
|
||||
[self.connection.relationship name], self.connection.keyPath, self.value];
|
||||
}
|
||||
}
|
||||
|
||||
return [super description];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -419,10 +442,9 @@ NSString * const RKMappingTestVerificationFailureException = @"RKMappingTestVeri
|
||||
[self addEvent:[RKMappingTestEvent eventWithMapping:mapping value:value]];
|
||||
}
|
||||
|
||||
- (void)mappingOperation:(RKMappingOperation *)operation didConnectRelationship:(NSRelationshipDescription *)relationship usingMapping:(RKConnectionMapping *)connectionMapping
|
||||
- (void)mappingOperation:(RKMappingOperation *)operation didConnectRelationship:(NSRelationshipDescription *)relationship toValue:(id)value usingConnection:(RKConnectionDescription *)connection
|
||||
{
|
||||
id connectedObjects = [operation.destinationObject valueForKey:relationship.name];
|
||||
[self addEvent:[RKMappingTestEvent eventWithMapping:connectionMapping value:connectedObjects]];
|
||||
[self addEvent:[RKMappingTestEvent eventWithConnection:connection value:value]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
2
Gemfile
2
Gemfile
@@ -8,4 +8,4 @@ gem 'xcoder', :git => "git://github.com/rayh/xcoder.git"
|
||||
gem 'restkit', :git => 'git://github.com/RestKit/RestKit-Gem.git'
|
||||
gem 'debugger', '1.2.0'
|
||||
gem 'faker', '1.1.2'
|
||||
gem 'cocoapods', '0.16.0.rc3'
|
||||
gem 'cocoapods', '0.16.0'
|
||||
|
||||
16
Gemfile.lock
16
Gemfile.lock
@@ -27,12 +27,12 @@ GIT
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
activesupport (3.2.8)
|
||||
activesupport (3.2.9)
|
||||
i18n (~> 0.6)
|
||||
multi_json (~> 1.0)
|
||||
addressable (2.3.2)
|
||||
builder (3.1.3)
|
||||
cocoapods (0.16.0.rc3)
|
||||
cocoapods (0.16.0)
|
||||
activesupport (~> 3.2.6)
|
||||
colored (~> 1.2)
|
||||
escape (~> 0.0.4)
|
||||
@@ -40,8 +40,8 @@ GEM
|
||||
json (~> 1.7.3)
|
||||
octokit (~> 1.7)
|
||||
open4 (~> 1.3.0)
|
||||
rake (~> 0.9.0)
|
||||
xcodeproj (~> 0.4.0.rc6)
|
||||
rake (~> 0.9.4)
|
||||
xcodeproj (~> 0.4.0)
|
||||
colored (1.2)
|
||||
columnize (0.3.6)
|
||||
daemons (1.1.9)
|
||||
@@ -78,7 +78,7 @@ GEM
|
||||
rack (1.4.1)
|
||||
rack-protection (1.2.0)
|
||||
rack
|
||||
rake (0.9.2.2)
|
||||
rake (0.9.5)
|
||||
rest-client (1.6.7)
|
||||
mime-types (>= 1.16)
|
||||
thin (1.5.0)
|
||||
@@ -86,16 +86,14 @@ GEM
|
||||
eventmachine (>= 0.12.6)
|
||||
rack (>= 1.0.0)
|
||||
tilt (1.3.3)
|
||||
xcodeproj (0.4.0.rc8)
|
||||
activesupport (~> 3.2.6)
|
||||
colored (~> 1.2)
|
||||
xcodeproj (0.4.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
bundler (~> 1.2.0)
|
||||
cocoapods (= 0.16.0.rc3)
|
||||
cocoapods (= 0.16.0)
|
||||
debugger (= 1.2.0)
|
||||
faker (= 1.1.2)
|
||||
rake (~> 0.9.0)
|
||||
|
||||
6
Podfile
6
Podfile
@@ -2,7 +2,7 @@ platform :ios, '5.0'
|
||||
link_with ['RestKitTests', 'RestKitFrameworkTests']
|
||||
inhibit_all_warnings!
|
||||
|
||||
pod 'Kiwi', '1.1.0'
|
||||
pod 'Specta', '0.1.6'
|
||||
pod 'OCMock', '2.0.1.classmocks', :git => 'git@github.com:blakewatters/ocmock.git'
|
||||
pod 'OCHamcrest', :head
|
||||
pod 'Expecta', '0.2.0'
|
||||
pod 'OCHamcrest', '1.9'
|
||||
pod 'Expecta', '0.2.0', :git => 'git@github.com:blakewatters/expecta.git', :branch => 'feature/expect-raise-with-reason'
|
||||
|
||||
21
Podfile.lock
21
Podfile.lock
@@ -1,24 +1,27 @@
|
||||
|
||||
PODS:
|
||||
- Expecta (0.2.0)
|
||||
- Kiwi (1.1.0)
|
||||
- OCHamcrest (HEAD based on 1.8)
|
||||
- OCHamcrest (1.9)
|
||||
- OCMock (2.0.1.classmocks)
|
||||
- Specta (0.1.6)
|
||||
|
||||
DEPENDENCIES:
|
||||
- Expecta (= 0.2.0)
|
||||
- Kiwi (= 1.1.0)
|
||||
- OCHamcrest (HEAD)
|
||||
- Expecta (from `git@github.com:blakewatters/expecta.git', branch `feature/expect-raise-with-reason')
|
||||
- OCHamcrest (= 1.9)
|
||||
- OCMock (from `git@github.com:blakewatters/ocmock.git')
|
||||
- Specta (= 0.1.6)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
Expecta:
|
||||
:git: git@github.com:blakewatters/expecta.git
|
||||
:branch: feature/expect-raise-with-reason
|
||||
OCMock:
|
||||
:git: git@github.com:blakewatters/ocmock.git
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Expecta: 1521da8c54c253277d5fae673f516c76ed838bc7
|
||||
Kiwi: 9141d15cf4f52a2178139ea16722f021b4059906
|
||||
OCHamcrest: 75258b3746b118ed9de96a6a8d985546f32e0f9b
|
||||
Expecta: 3ddfc757aeb1e351e12c6f1e21ab631f77178f13
|
||||
OCHamcrest: 200532155c3099e6e8b5a3e061d22d063033e077
|
||||
OCMock: 5ab9b659efcd39b4ca4825628bee3df51a189ff8
|
||||
Specta: ec7e1ce376442fc26b927dbc517c90e36232cde6
|
||||
|
||||
COCOAPODS: 0.16.0.rc3
|
||||
COCOAPODS: 0.16.0
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
0BD827D1939444AF9897B48F /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C8C87FF6727A42D68CA2220E /* libPods.a */; };
|
||||
0D24428768594AB590873733 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DA82BFA2A774416B4AA69A9 /* libPods.a */; };
|
||||
17D2D51D9E864B2F9D9BCED0 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DA82BFA2A774416B4AA69A9 /* libPods.a */; };
|
||||
25019495166406E30081D68A /* RKValueTransformers.h in Headers */ = {isa = PBXBuildFile; fileRef = 25019493166406E30081D68A /* RKValueTransformers.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
25019496166406E30081D68A /* RKValueTransformers.h in Headers */ = {isa = PBXBuildFile; fileRef = 25019493166406E30081D68A /* RKValueTransformers.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
25019497166406E30081D68A /* RKValueTransformers.m in Sources */ = {isa = PBXBuildFile; fileRef = 25019494166406E30081D68A /* RKValueTransformers.m */; };
|
||||
25019498166406E30081D68A /* RKValueTransformers.m in Sources */ = {isa = PBXBuildFile; fileRef = 25019494166406E30081D68A /* RKValueTransformers.m */; };
|
||||
2502C8ED15F79CF70060FD75 /* CoreData.h in Headers */ = {isa = PBXBuildFile; fileRef = 2502C8E715F79CF70060FD75 /* CoreData.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
2502C8EE15F79CF70060FD75 /* CoreData.h in Headers */ = {isa = PBXBuildFile; fileRef = 2502C8E715F79CF70060FD75 /* CoreData.h */; };
|
||||
2502C8EF15F79CF70060FD75 /* Network.h in Headers */ = {isa = PBXBuildFile; fileRef = 2502C8E815F79CF70060FD75 /* Network.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -37,12 +39,6 @@
|
||||
25055B9314EEFEC800B9C4DD /* libRestKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 25160D1614564E810060A5C5 /* libRestKit.a */; };
|
||||
2506759F162DEA25003210B0 /* RKEntityMappingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 25160FC91456F2330060A5C5 /* RKEntityMappingTest.m */; };
|
||||
250675A1162DEA27003210B0 /* RKEntityMappingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 25160FC91456F2330060A5C5 /* RKEntityMappingTest.m */; };
|
||||
25079C6F151B93DB00266AE7 /* NSEntityDescription+RKAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 25079C6D151B93DB00266AE7 /* NSEntityDescription+RKAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
25079C70151B93DB00266AE7 /* NSEntityDescription+RKAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 25079C6D151B93DB00266AE7 /* NSEntityDescription+RKAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
25079C71151B93DB00266AE7 /* NSEntityDescription+RKAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 25079C6E151B93DB00266AE7 /* NSEntityDescription+RKAdditions.m */; };
|
||||
25079C72151B93DB00266AE7 /* NSEntityDescription+RKAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 25079C6E151B93DB00266AE7 /* NSEntityDescription+RKAdditions.m */; };
|
||||
25079C76151B952200266AE7 /* NSEntityDescription+RKAdditionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 25079C75151B952200266AE7 /* NSEntityDescription+RKAdditionsTest.m */; };
|
||||
25079C77151B952200266AE7 /* NSEntityDescription+RKAdditionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 25079C75151B952200266AE7 /* NSEntityDescription+RKAdditionsTest.m */; };
|
||||
2507C327161BD5C700EA71FF /* RKTestHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 2507C325161BD5C700EA71FF /* RKTestHelpers.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
2507C328161BD5C700EA71FF /* RKTestHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 2507C325161BD5C700EA71FF /* RKTestHelpers.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
2507C329161BD5C700EA71FF /* RKTestHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 2507C326161BD5C700EA71FF /* RKTestHelpers.m */; };
|
||||
@@ -361,6 +357,10 @@
|
||||
254372D715F54CE3006E8424 /* RKManagedObjectRequestOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 254372D415F54CE3006E8424 /* RKManagedObjectRequestOperation.h */; };
|
||||
254372D815F54CE3006E8424 /* RKManagedObjectRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 254372D515F54CE3006E8424 /* RKManagedObjectRequestOperation.m */; };
|
||||
254372D915F54CE3006E8424 /* RKManagedObjectRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 254372D515F54CE3006E8424 /* RKManagedObjectRequestOperation.m */; };
|
||||
2543A25D1664FD3100821D5B /* RKResponseDescriptorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 25CC5C58161DDADD0008BD21 /* RKResponseDescriptorTest.m */; };
|
||||
2543A25E1664FD3200821D5B /* RKResponseDescriptorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 25CC5C58161DDADD0008BD21 /* RKResponseDescriptorTest.m */; };
|
||||
2546A95816628EDD0078E044 /* RKConnectionDescriptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 2546A95716628EDD0078E044 /* RKConnectionDescriptionTest.m */; };
|
||||
2546A95916628EDD0078E044 /* RKConnectionDescriptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 2546A95716628EDD0078E044 /* RKConnectionDescriptionTest.m */; };
|
||||
2548AC6D162F5E00009E79BF /* RKManagedObjectRequestOperationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 2548AC6C162F5E00009E79BF /* RKManagedObjectRequestOperationTest.m */; };
|
||||
2548AC6E162F5E00009E79BF /* RKManagedObjectRequestOperationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 2548AC6C162F5E00009E79BF /* RKManagedObjectRequestOperationTest.m */; };
|
||||
2549D646162B376F003DD135 /* RKRequestDescriptorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 2549D645162B376F003DD135 /* RKRequestDescriptorTest.m */; };
|
||||
@@ -399,10 +399,10 @@
|
||||
2595B47415F670530087A59B /* RKNSJSONSerialization.h in Headers */ = {isa = PBXBuildFile; fileRef = 2595B46D15F670530087A59B /* RKNSJSONSerialization.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
2595B47515F670530087A59B /* RKNSJSONSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 2595B46E15F670530087A59B /* RKNSJSONSerialization.m */; };
|
||||
2595B47615F670530087A59B /* RKNSJSONSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 2595B46E15F670530087A59B /* RKNSJSONSerialization.m */; };
|
||||
2597F99C15AF6DC400E547D7 /* RKRelationshipConnectionOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 2597F99A15AF6DC400E547D7 /* RKRelationshipConnectionOperation.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
2597F99D15AF6DC400E547D7 /* RKRelationshipConnectionOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 2597F99A15AF6DC400E547D7 /* RKRelationshipConnectionOperation.h */; };
|
||||
2597F99E15AF6DC400E547D7 /* RKRelationshipConnectionOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 2597F99B15AF6DC400E547D7 /* RKRelationshipConnectionOperation.m */; };
|
||||
2597F99F15AF6DC400E547D7 /* RKRelationshipConnectionOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 2597F99B15AF6DC400E547D7 /* RKRelationshipConnectionOperation.m */; };
|
||||
2597F99C15AF6DC400E547D7 /* RKConnectionOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 2597F99A15AF6DC400E547D7 /* RKConnectionOperation.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
2597F99D15AF6DC400E547D7 /* RKConnectionOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 2597F99A15AF6DC400E547D7 /* RKConnectionOperation.h */; };
|
||||
2597F99E15AF6DC400E547D7 /* RKConnectionOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 2597F99B15AF6DC400E547D7 /* RKConnectionOperation.m */; };
|
||||
2597F99F15AF6DC400E547D7 /* RKConnectionOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 2597F99B15AF6DC400E547D7 /* RKConnectionOperation.m */; };
|
||||
2598888D15EC169E006CAE95 /* RKPropertyMapping.h in Headers */ = {isa = PBXBuildFile; fileRef = 2598888B15EC169E006CAE95 /* RKPropertyMapping.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
2598888E15EC169E006CAE95 /* RKPropertyMapping.h in Headers */ = {isa = PBXBuildFile; fileRef = 2598888B15EC169E006CAE95 /* RKPropertyMapping.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
2598888F15EC169E006CAE95 /* RKPropertyMapping.m in Sources */ = {isa = PBXBuildFile; fileRef = 2598888C15EC169E006CAE95 /* RKPropertyMapping.m */; };
|
||||
@@ -479,7 +479,6 @@
|
||||
25AA23D815AF5085006EF62D /* RKManagedObjectMappingOperationDataSourceTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 25AA23D315AF4F25006EF62D /* RKManagedObjectMappingOperationDataSourceTest.m */; };
|
||||
25AA23D915AF5086006EF62D /* RKManagedObjectMappingOperationDataSourceTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 25AA23D315AF4F25006EF62D /* RKManagedObjectMappingOperationDataSourceTest.m */; };
|
||||
25AE61CA15ADEBD000B319C8 /* RKConnectionMapping.h in Headers */ = {isa = PBXBuildFile; fileRef = 8BC044C81576CE72003DCDD6 /* RKConnectionMapping.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
25AE61DE15ADEF5800B319C8 /* RKConnectionMapping.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BC044C91576CE72003DCDD6 /* RKConnectionMapping.m */; };
|
||||
25AFF8F115B4CF1F0051877F /* RKMappingErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = 25AFF8F015B4CF1F0051877F /* RKMappingErrors.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
25AFF8F215B4CF1F0051877F /* RKMappingErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = 25AFF8F015B4CF1F0051877F /* RKMappingErrors.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
25B408261491CDDC00F21111 /* RKPathUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 25B408241491CDDB00F21111 /* RKPathUtilities.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -514,8 +513,6 @@
|
||||
25CA7A9114EC5C2D00888FF8 /* RKTestFixture.m in Sources */ = {isa = PBXBuildFile; fileRef = 252EFB2114D9B35D004863C8 /* RKTestFixture.m */; };
|
||||
25CAAA9415254E7800CAE5D7 /* ArrayOfHumans.json in Resources */ = {isa = PBXBuildFile; fileRef = 25CAAA9315254E7800CAE5D7 /* ArrayOfHumans.json */; };
|
||||
25CAAA9515254E7800CAE5D7 /* ArrayOfHumans.json in Resources */ = {isa = PBXBuildFile; fileRef = 25CAAA9315254E7800CAE5D7 /* ArrayOfHumans.json */; };
|
||||
25CC5C59161DDADD0008BD21 /* RKResponseDescriptorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 25CC5C58161DDADD0008BD21 /* RKResponseDescriptorTest.m */; };
|
||||
25CC5C5A161DDADD0008BD21 /* RKResponseDescriptorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 25CC5C58161DDADD0008BD21 /* RKResponseDescriptorTest.m */; };
|
||||
25CDA0DC161E7ED400F583F3 /* RKISO8601DateFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = 25CDA0DA161E7ED400F583F3 /* RKISO8601DateFormatter.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
25CDA0DD161E7ED400F583F3 /* RKISO8601DateFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = 25CDA0DA161E7ED400F583F3 /* RKISO8601DateFormatter.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
25CDA0DE161E7ED400F583F3 /* RKISO8601DateFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 25CDA0DB161E7ED400F583F3 /* RKISO8601DateFormatter.m */; };
|
||||
@@ -526,6 +523,16 @@
|
||||
25DB7509151BD551009F01AF /* NSManagedObjectContext+RKAdditionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 25DB7507151BD551009F01AF /* NSManagedObjectContext+RKAdditionsTest.m */; };
|
||||
25E36E0215195CED00F9E448 /* RKFetchRequestMappingCacheTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 25E36E0115195CED00F9E448 /* RKFetchRequestMappingCacheTest.m */; };
|
||||
25E36E0315195CED00F9E448 /* RKFetchRequestMappingCacheTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 25E36E0115195CED00F9E448 /* RKFetchRequestMappingCacheTest.m */; };
|
||||
25E88C82165C5B580042ABD0 /* RKEntityIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 25E88C80165C5B580042ABD0 /* RKEntityIdentifier.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
25E88C83165C5B580042ABD0 /* RKEntityIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 25E88C80165C5B580042ABD0 /* RKEntityIdentifier.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
25E88C84165C5B580042ABD0 /* RKEntityIdentifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 25E88C81165C5B580042ABD0 /* RKEntityIdentifier.m */; };
|
||||
25E88C85165C5B580042ABD0 /* RKEntityIdentifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 25E88C81165C5B580042ABD0 /* RKEntityIdentifier.m */; };
|
||||
25E88C88165C5CC30042ABD0 /* RKConnectionDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 25E88C86165C5CC30042ABD0 /* RKConnectionDescription.h */; };
|
||||
25E88C89165C5CC30042ABD0 /* RKConnectionDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = 25E88C86165C5CC30042ABD0 /* RKConnectionDescription.h */; };
|
||||
25E88C8A165C5CC30042ABD0 /* RKConnectionDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 25E88C87165C5CC30042ABD0 /* RKConnectionDescription.m */; };
|
||||
25E88C8B165C5CC30042ABD0 /* RKConnectionDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 25E88C87165C5CC30042ABD0 /* RKConnectionDescription.m */; };
|
||||
25E88C8E165C87FF0042ABD0 /* RKEntityIdentifierTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 25E88C8D165C87FF0042ABD0 /* RKEntityIdentifierTest.m */; };
|
||||
25E88C8F165C87FF0042ABD0 /* RKEntityIdentifierTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 25E88C8D165C87FF0042ABD0 /* RKEntityIdentifierTest.m */; };
|
||||
25E9C8F01612523400647F84 /* RKObjectParameterizationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 251610261456F2330060A5C5 /* RKObjectParameterizationTest.m */; };
|
||||
25E9C8F1161290D500647F84 /* RKObjectParameterization.m in Sources */ = {isa = PBXBuildFile; fileRef = 254372A715F54995006E8424 /* RKObjectParameterization.m */; };
|
||||
25EC1A3914F72B0900C3CF3F /* RKFetchRequestManagedObjectCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 7394DF3814CF168C00CE7BCE /* RKFetchRequestManagedObjectCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -555,7 +562,8 @@
|
||||
25FBB854159272DD00955D27 /* RKRouter.m in Sources */ = {isa = PBXBuildFile; fileRef = 25FBB851159272DD00955D27 /* RKRouter.m */; };
|
||||
25FBB855159272DD00955D27 /* RKRouter.m in Sources */ = {isa = PBXBuildFile; fileRef = 25FBB851159272DD00955D27 /* RKRouter.m */; };
|
||||
36F3D0E4FD7C4C4AA2B4FEB2 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C8C87FF6727A42D68CA2220E /* libPods.a */; };
|
||||
5738A4C11A81415DBD72C58B /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 04014C1F2EA945798F953D38 /* libPods.a */; };
|
||||
4904440427614B4891C90CC2 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D87B44252FCE4651B291E38A /* libPods.a */; };
|
||||
58C29921F7E1482AB5B66E3A /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 93B7B61F0199413CAA60E8A7 /* libPods.a */; };
|
||||
5C927E141608FFFD00DC8B07 /* RKDictionaryUtilitiesTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C927E131608FFFD00DC8B07 /* RKDictionaryUtilitiesTest.m */; };
|
||||
5C927E151608FFFD00DC8B07 /* RKDictionaryUtilitiesTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C927E131608FFFD00DC8B07 /* RKDictionaryUtilitiesTest.m */; };
|
||||
5CCC295615B7124A0045F0F5 /* RKMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CCC295515B7124A0045F0F5 /* RKMacros.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -567,7 +575,6 @@
|
||||
73D3907914CA1DD40093E3D6 /* channels.xml in Resources */ = {isa = PBXBuildFile; fileRef = 73D3907814CA1D710093E3D6 /* channels.xml */; };
|
||||
73D3907A14CA1DD50093E3D6 /* channels.xml in Resources */ = {isa = PBXBuildFile; fileRef = 73D3907814CA1D710093E3D6 /* channels.xml */; };
|
||||
8BC044CA1576CE72003DCDD6 /* RKConnectionMapping.h in Headers */ = {isa = PBXBuildFile; fileRef = 8BC044C81576CE72003DCDD6 /* RKConnectionMapping.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
8BC044CB1576CE72003DCDD6 /* RKConnectionMapping.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BC044C91576CE72003DCDD6 /* RKConnectionMapping.m */; };
|
||||
AAB37371906649BD90E20FAF /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 04014C1F2EA945798F953D38 /* libPods.a */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@@ -603,6 +610,8 @@
|
||||
/* Begin PBXFileReference section */
|
||||
04014C1F2EA945798F953D38 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
2501405215366000004E0466 /* RKObjectiveCppTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RKObjectiveCppTest.mm; sourceTree = "<group>"; };
|
||||
25019493166406E30081D68A /* RKValueTransformers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKValueTransformers.h; sourceTree = "<group>"; };
|
||||
25019494166406E30081D68A /* RKValueTransformers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKValueTransformers.m; sourceTree = "<group>"; };
|
||||
2502C8E715F79CF70060FD75 /* CoreData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoreData.h; sourceTree = "<group>"; };
|
||||
2502C8E815F79CF70060FD75 /* Network.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Network.h; sourceTree = "<group>"; };
|
||||
2502C8E915F79CF70060FD75 /* ObjectMapping.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectMapping.h; sourceTree = "<group>"; };
|
||||
@@ -815,6 +824,7 @@
|
||||
254372B715F54C3F006E8424 /* RKResponseMapperOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKResponseMapperOperation.m; sourceTree = "<group>"; };
|
||||
254372D415F54CE3006E8424 /* RKManagedObjectRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKManagedObjectRequestOperation.h; sourceTree = "<group>"; };
|
||||
254372D515F54CE3006E8424 /* RKManagedObjectRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKManagedObjectRequestOperation.m; sourceTree = "<group>"; };
|
||||
2546A95716628EDD0078E044 /* RKConnectionDescriptionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKConnectionDescriptionTest.m; sourceTree = "<group>"; };
|
||||
2548AC6C162F5E00009E79BF /* RKManagedObjectRequestOperationTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKManagedObjectRequestOperationTest.m; sourceTree = "<group>"; };
|
||||
2549D645162B376F003DD135 /* RKRequestDescriptorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKRequestDescriptorTest.m; sourceTree = "<group>"; };
|
||||
254A62BF14AD591C00939BEE /* RKPaginatorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKPaginatorTest.m; sourceTree = "<group>"; };
|
||||
@@ -835,8 +845,8 @@
|
||||
2595B46C15F670530087A59B /* RKMIMETypeSerialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKMIMETypeSerialization.m; sourceTree = "<group>"; };
|
||||
2595B46D15F670530087A59B /* RKNSJSONSerialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKNSJSONSerialization.h; sourceTree = "<group>"; };
|
||||
2595B46E15F670530087A59B /* RKNSJSONSerialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKNSJSONSerialization.m; sourceTree = "<group>"; };
|
||||
2597F99A15AF6DC400E547D7 /* RKRelationshipConnectionOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKRelationshipConnectionOperation.h; sourceTree = "<group>"; };
|
||||
2597F99B15AF6DC400E547D7 /* RKRelationshipConnectionOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKRelationshipConnectionOperation.m; sourceTree = "<group>"; };
|
||||
2597F99A15AF6DC400E547D7 /* RKConnectionOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKConnectionOperation.h; sourceTree = "<group>"; };
|
||||
2597F99B15AF6DC400E547D7 /* RKConnectionOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKConnectionOperation.m; sourceTree = "<group>"; };
|
||||
2598888B15EC169E006CAE95 /* RKPropertyMapping.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKPropertyMapping.h; sourceTree = "<group>"; };
|
||||
2598888C15EC169E006CAE95 /* RKPropertyMapping.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKPropertyMapping.m; sourceTree = "<group>"; };
|
||||
259AC480162B05C80012D2F9 /* RKObjectRequestOperationTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKObjectRequestOperationTest.m; sourceTree = "<group>"; };
|
||||
@@ -901,6 +911,11 @@
|
||||
25CDA0E2161E821000F583F3 /* RKISODateFormatterTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKISODateFormatterTest.m; sourceTree = "<group>"; };
|
||||
25DB7507151BD551009F01AF /* NSManagedObjectContext+RKAdditionsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObjectContext+RKAdditionsTest.m"; sourceTree = "<group>"; };
|
||||
25E36E0115195CED00F9E448 /* RKFetchRequestMappingCacheTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKFetchRequestMappingCacheTest.m; sourceTree = "<group>"; };
|
||||
25E88C80165C5B580042ABD0 /* RKEntityIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKEntityIdentifier.h; sourceTree = "<group>"; };
|
||||
25E88C81165C5B580042ABD0 /* RKEntityIdentifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKEntityIdentifier.m; sourceTree = "<group>"; };
|
||||
25E88C86165C5CC30042ABD0 /* RKConnectionDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKConnectionDescription.h; sourceTree = "<group>"; };
|
||||
25E88C87165C5CC30042ABD0 /* RKConnectionDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKConnectionDescription.m; sourceTree = "<group>"; };
|
||||
25E88C8D165C87FF0042ABD0 /* RKEntityIdentifierTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKEntityIdentifierTest.m; sourceTree = "<group>"; };
|
||||
25EC1AD814F8022600C3CF3F /* RestKitFramework-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "RestKitFramework-Info.plist"; sourceTree = "<group>"; };
|
||||
25EC1AD914F8022600C3CF3F /* RestKitFrameworkTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "RestKitFrameworkTests-Info.plist"; sourceTree = "<group>"; };
|
||||
25EC1ADA14F8022600C3CF3F /* RestKitTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "RestKitTests-Info.plist"; sourceTree = "<group>"; };
|
||||
@@ -926,9 +941,13 @@
|
||||
73D3907814CA1D710093E3D6 /* channels.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = channels.xml; sourceTree = "<group>"; };
|
||||
8BC044C81576CE72003DCDD6 /* RKConnectionMapping.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RKConnectionMapping.h; sourceTree = "<group>"; };
|
||||
8BC044C91576CE72003DCDD6 /* RKConnectionMapping.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RKConnectionMapping.m; sourceTree = "<group>"; };
|
||||
92A418BC16A64A74BF92549F /* Pods.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.xcconfig; path = Pods/Pods.xcconfig; sourceTree = SOURCE_ROOT; };
|
||||
93B7B61F0199413CAA60E8A7 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
964648386780496FA49D3DD6 /* Pods.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.xcconfig; path = Pods/Pods.xcconfig; sourceTree = SOURCE_ROOT; };
|
||||
C4123D3CDB2C42AE86B273D7 /* Pods.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.xcconfig; path = Pods/Pods.xcconfig; sourceTree = SOURCE_ROOT; };
|
||||
C87136726FCA44FBBC18C515 /* Pods.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.xcconfig; path = Pods/Pods.xcconfig; sourceTree = SOURCE_ROOT; };
|
||||
C8C87FF6727A42D68CA2220E /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D87B44252FCE4651B291E38A /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
E79F34A511E54F35B6580DA7 /* Pods.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.xcconfig; path = Pods/Pods.xcconfig; sourceTree = SOURCE_ROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
@@ -958,9 +977,7 @@
|
||||
25160D2814564E820060A5C5 /* SenTestingKit.framework in Frameworks */,
|
||||
25160D2A14564E820060A5C5 /* UIKit.framework in Frameworks */,
|
||||
25160D2B14564E820060A5C5 /* Foundation.framework in Frameworks */,
|
||||
0BD827D1939444AF9897B48F /* libPods.a in Frameworks */,
|
||||
0D24428768594AB590873733 /* libPods.a in Frameworks */,
|
||||
5738A4C11A81415DBD72C58B /* libPods.a in Frameworks */,
|
||||
4904440427614B4891C90CC2 /* libPods.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -986,6 +1003,7 @@
|
||||
36F3D0E4FD7C4C4AA2B4FEB2 /* libPods.a in Frameworks */,
|
||||
17D2D51D9E864B2F9D9BCED0 /* libPods.a in Frameworks */,
|
||||
AAB37371906649BD90E20FAF /* libPods.a in Frameworks */,
|
||||
58C29921F7E1482AB5B66E3A /* libPods.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -1034,6 +1052,8 @@
|
||||
C4123D3CDB2C42AE86B273D7 /* Pods.xcconfig */,
|
||||
E79F34A511E54F35B6580DA7 /* Pods.xcconfig */,
|
||||
C87136726FCA44FBBC18C515 /* Pods.xcconfig */,
|
||||
92A418BC16A64A74BF92549F /* Pods.xcconfig */,
|
||||
964648386780496FA49D3DD6 /* Pods.xcconfig */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
@@ -1073,6 +1093,8 @@
|
||||
C8C87FF6727A42D68CA2220E /* libPods.a */,
|
||||
5DA82BFA2A774416B4AA69A9 /* libPods.a */,
|
||||
04014C1F2EA945798F953D38 /* libPods.a */,
|
||||
93B7B61F0199413CAA60E8A7 /* libPods.a */,
|
||||
D87B44252FCE4651B291E38A /* libPods.a */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
@@ -1106,8 +1128,8 @@
|
||||
E4081E0915FB8FD800364948 /* Mapping */,
|
||||
25160D52145650490060A5C5 /* RKManagedObjectStore.h */,
|
||||
25160D53145650490060A5C5 /* RKManagedObjectStore.m */,
|
||||
2597F99A15AF6DC400E547D7 /* RKRelationshipConnectionOperation.h */,
|
||||
2597F99B15AF6DC400E547D7 /* RKRelationshipConnectionOperation.m */,
|
||||
2597F99A15AF6DC400E547D7 /* RKConnectionOperation.h */,
|
||||
2597F99B15AF6DC400E547D7 /* RKConnectionOperation.m */,
|
||||
);
|
||||
path = CoreData;
|
||||
sourceTree = "<group>";
|
||||
@@ -1171,6 +1193,8 @@
|
||||
2598888C15EC169E006CAE95 /* RKPropertyMapping.m */,
|
||||
25A226D41618A57500952D72 /* RKObjectUtilities.h */,
|
||||
25A226D51618A57500952D72 /* RKObjectUtilities.m */,
|
||||
25019493166406E30081D68A /* RKValueTransformers.h */,
|
||||
25019494166406E30081D68A /* RKValueTransformers.m */,
|
||||
);
|
||||
path = ObjectMapping;
|
||||
sourceTree = "<group>";
|
||||
@@ -1299,6 +1323,8 @@
|
||||
25AA23D315AF4F25006EF62D /* RKManagedObjectMappingOperationDataSourceTest.m */,
|
||||
258EFF7915C0CE1400EE4E0D /* RKManagedObjectSeederTest.m */,
|
||||
2564E40A16173F7B00C12D7D /* RKRelationshipConnectionOperationTest.m */,
|
||||
25E88C8D165C87FF0042ABD0 /* RKEntityIdentifierTest.m */,
|
||||
2546A95716628EDD0078E044 /* RKConnectionDescriptionTest.m */,
|
||||
);
|
||||
name = CoreData;
|
||||
path = Logic/CoreData;
|
||||
@@ -1603,6 +1629,8 @@
|
||||
259D98531550C69A008C90F5 /* RKEntityByAttributeCache.m */,
|
||||
259D985C155218E4008C90F5 /* RKEntityCache.h */,
|
||||
259D985D155218E4008C90F5 /* RKEntityCache.m */,
|
||||
25E88C80165C5B580042ABD0 /* RKEntityIdentifier.h */,
|
||||
25E88C81165C5B580042ABD0 /* RKEntityIdentifier.m */,
|
||||
);
|
||||
name = ManagedObjectCaching;
|
||||
sourceTree = "<group>";
|
||||
@@ -1665,6 +1693,8 @@
|
||||
25160D4D145650490060A5C5 /* RKEntityMapping.m */,
|
||||
258EA4B015A3908F007E07A6 /* RKManagedObjectMappingOperationDataSource.h */,
|
||||
25AA23CF15AF291F006EF62D /* RKManagedObjectMappingOperationDataSource.m */,
|
||||
25E88C86165C5CC30042ABD0 /* RKConnectionDescription.h */,
|
||||
25E88C87165C5CC30042ABD0 /* RKConnectionDescription.m */,
|
||||
);
|
||||
name = Mapping;
|
||||
sourceTree = "<group>";
|
||||
@@ -1717,7 +1747,6 @@
|
||||
25EC1A6314F7402A00C3CF3F /* RKManagedObjectCaching.h in Headers */,
|
||||
257ABAB015112DD500CCAA76 /* NSManagedObjectContext+RKAdditions.h in Headers */,
|
||||
257ABAB61511371E00CCAA76 /* NSManagedObject+RKAdditions.h in Headers */,
|
||||
25079C6F151B93DB00266AE7 /* NSEntityDescription+RKAdditions.h in Headers */,
|
||||
259D98541550C69A008C90F5 /* RKEntityByAttributeCache.h in Headers */,
|
||||
259D985E155218E5008C90F5 /* RKEntityCache.h in Headers */,
|
||||
8BC044CA1576CE72003DCDD6 /* RKConnectionMapping.h in Headers */,
|
||||
@@ -1727,7 +1756,7 @@
|
||||
258EA4A815A38BC0007E07A6 /* RKObjectMappingOperationDataSource.h in Headers */,
|
||||
258EA4AE15A38E7E007E07A6 /* RKMappingOperationDataSource.h in Headers */,
|
||||
258EA4B215A39090007E07A6 /* RKManagedObjectMappingOperationDataSource.h in Headers */,
|
||||
2597F99C15AF6DC400E547D7 /* RKRelationshipConnectionOperation.h in Headers */,
|
||||
2597F99C15AF6DC400E547D7 /* RKConnectionOperation.h in Headers */,
|
||||
25AFF8F115B4CF1F0051877F /* RKMappingErrors.h in Headers */,
|
||||
5CCC295615B7124A0045F0F5 /* RKMacros.h in Headers */,
|
||||
25104F1F15C30CD900829135 /* RKSearchWord.h in Headers */,
|
||||
@@ -1772,6 +1801,9 @@
|
||||
25A226D61618A57500952D72 /* RKObjectUtilities.h in Headers */,
|
||||
2507C327161BD5C700EA71FF /* RKTestHelpers.h in Headers */,
|
||||
25CDA0DC161E7ED400F583F3 /* RKISO8601DateFormatter.h in Headers */,
|
||||
25E88C82165C5B580042ABD0 /* RKEntityIdentifier.h in Headers */,
|
||||
25E88C88165C5CC30042ABD0 /* RKConnectionDescription.h in Headers */,
|
||||
25019495166406E30081D68A /* RKValueTransformers.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -1818,7 +1850,6 @@
|
||||
25EC1A6514F7402A00C3CF3F /* RKManagedObjectCaching.h in Headers */,
|
||||
257ABAB115112DD500CCAA76 /* NSManagedObjectContext+RKAdditions.h in Headers */,
|
||||
257ABAB71511371E00CCAA76 /* NSManagedObject+RKAdditions.h in Headers */,
|
||||
25079C70151B93DB00266AE7 /* NSEntityDescription+RKAdditions.h in Headers */,
|
||||
259D98551550C69A008C90F5 /* RKEntityByAttributeCache.h in Headers */,
|
||||
259D985F155218E5008C90F5 /* RKEntityCache.h in Headers */,
|
||||
25AE61CA15ADEBD000B319C8 /* RKConnectionMapping.h in Headers */,
|
||||
@@ -1828,7 +1859,7 @@
|
||||
258EA4A915A38BC0007E07A6 /* RKObjectMappingOperationDataSource.h in Headers */,
|
||||
258EA4AF15A38E7E007E07A6 /* RKMappingOperationDataSource.h in Headers */,
|
||||
258EA4B315A39090007E07A6 /* RKManagedObjectMappingOperationDataSource.h in Headers */,
|
||||
2597F99D15AF6DC400E547D7 /* RKRelationshipConnectionOperation.h in Headers */,
|
||||
2597F99D15AF6DC400E547D7 /* RKConnectionOperation.h in Headers */,
|
||||
25AFF8F215B4CF1F0051877F /* RKMappingErrors.h in Headers */,
|
||||
5CCC295715B7124A0045F0F5 /* RKMacros.h in Headers */,
|
||||
25104F2015C30CD900829135 /* RKSearchWord.h in Headers */,
|
||||
@@ -1872,6 +1903,9 @@
|
||||
25A226D71618A57500952D72 /* RKObjectUtilities.h in Headers */,
|
||||
2507C328161BD5C700EA71FF /* RKTestHelpers.h in Headers */,
|
||||
25CDA0DD161E7ED400F583F3 /* RKISO8601DateFormatter.h in Headers */,
|
||||
25E88C83165C5B580042ABD0 /* RKEntityIdentifier.h in Headers */,
|
||||
25E88C89165C5CC30042ABD0 /* RKConnectionDescription.h in Headers */,
|
||||
25019496166406E30081D68A /* RKValueTransformers.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -1903,9 +1937,7 @@
|
||||
25160D2214564E820060A5C5 /* Frameworks */,
|
||||
25160D2314564E820060A5C5 /* Resources */,
|
||||
25160D2414564E820060A5C5 /* ShellScript */,
|
||||
F1C99E66F43D4A42AEF2B162 /* Copy Pods Resources */,
|
||||
A526A94CAA244A79A6DD3C2D /* Copy Pods Resources */,
|
||||
1D809DEA215D4BF9A822FD95 /* Copy Pods Resources */,
|
||||
4E6B40EB7B75407393E6F25D /* Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -1947,6 +1979,7 @@
|
||||
91F9BFD4685A46128EAED847 /* Copy Pods Resources */,
|
||||
31B1AB25BF2747C7A911C2B2 /* Copy Pods Resources */,
|
||||
CD932DC245F547468D56D003 /* Copy Pods Resources */,
|
||||
9B6CAFE1BB8842AAB5716036 /* Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -2091,20 +2124,6 @@
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
1D809DEA215D4BF9A822FD95 /* Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Copy Pods Resources";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Pods-resources.sh\"\n";
|
||||
};
|
||||
25160D2414564E820060A5C5 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -2145,6 +2164,20 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Pods-resources.sh\"\n";
|
||||
};
|
||||
4E6B40EB7B75407393E6F25D /* Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Copy Pods Resources";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Pods-resources.sh\"\n";
|
||||
};
|
||||
91F9BFD4685A46128EAED847 /* Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -2159,7 +2192,7 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Pods-resources.sh\"\n";
|
||||
};
|
||||
A526A94CAA244A79A6DD3C2D /* Copy Pods Resources */ = {
|
||||
9B6CAFE1BB8842AAB5716036 /* Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
@@ -2187,20 +2220,6 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Pods-resources.sh\"\n";
|
||||
};
|
||||
F1C99E66F43D4A42AEF2B162 /* Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Copy Pods Resources";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Pods-resources.sh\"\n";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
@@ -2241,17 +2260,15 @@
|
||||
25EC1A3F14F72B3100C3CF3F /* RKInMemoryManagedObjectCache.m in Sources */,
|
||||
257ABAB215112DD500CCAA76 /* NSManagedObjectContext+RKAdditions.m in Sources */,
|
||||
257ABAB81511371E00CCAA76 /* NSManagedObject+RKAdditions.m in Sources */,
|
||||
25079C71151B93DB00266AE7 /* NSEntityDescription+RKAdditions.m in Sources */,
|
||||
25C954A715542A47005C9E08 /* RKTestConstants.m in Sources */,
|
||||
259D98561550C69A008C90F5 /* RKEntityByAttributeCache.m in Sources */,
|
||||
259D9860155218E5008C90F5 /* RKEntityCache.m in Sources */,
|
||||
8BC044CB1576CE72003DCDD6 /* RKConnectionMapping.m in Sources */,
|
||||
252028FE1577AE0B00076FB4 /* RKRouteSet.m in Sources */,
|
||||
252029051577AE1800076FB4 /* RKRoute.m in Sources */,
|
||||
25FBB854159272DD00955D27 /* RKRouter.m in Sources */,
|
||||
258EA4AA15A38BC0007E07A6 /* RKObjectMappingOperationDataSource.m in Sources */,
|
||||
25AA23D015AF2920006EF62D /* RKManagedObjectMappingOperationDataSource.m in Sources */,
|
||||
2597F99E15AF6DC400E547D7 /* RKRelationshipConnectionOperation.m in Sources */,
|
||||
2597F99E15AF6DC400E547D7 /* RKConnectionOperation.m in Sources */,
|
||||
25104F2115C30CD900829135 /* RKSearchWord.m in Sources */,
|
||||
25104F2B15C30D1700829135 /* RKManagedObjectStore+RKSearchAdditions.m in Sources */,
|
||||
25104F3115C30E7400829135 /* RKSearchIndexer.m in Sources */,
|
||||
@@ -2286,6 +2303,9 @@
|
||||
25A226D81618A57500952D72 /* RKObjectUtilities.m in Sources */,
|
||||
2507C329161BD5C700EA71FF /* RKTestHelpers.m in Sources */,
|
||||
25CDA0DE161E7ED400F583F3 /* RKISO8601DateFormatter.m in Sources */,
|
||||
25E88C84165C5B580042ABD0 /* RKEntityIdentifier.m in Sources */,
|
||||
25E88C8A165C5CC30042ABD0 /* RKConnectionDescription.m in Sources */,
|
||||
25019497166406E30081D68A /* RKValueTransformers.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -2321,7 +2341,6 @@
|
||||
25B6E9DF14CF912500B1E881 /* RKTestUser.m in Sources */,
|
||||
252EFAFA14D8EAEC004863C8 /* RKEvent.m in Sources */,
|
||||
25E36E0215195CED00F9E448 /* RKFetchRequestMappingCacheTest.m in Sources */,
|
||||
25079C76151B952200266AE7 /* NSEntityDescription+RKAdditionsTest.m in Sources */,
|
||||
25DB7508151BD551009F01AF /* NSManagedObjectContext+RKAdditionsTest.m in Sources */,
|
||||
259D985A1550C6BE008C90F5 /* RKEntityByAttributeCacheTest.m in Sources */,
|
||||
259D986415521B20008C90F5 /* RKEntityCacheTest.m in Sources */,
|
||||
@@ -2338,7 +2357,6 @@
|
||||
25E9C8F01612523400647F84 /* RKObjectParameterizationTest.m in Sources */,
|
||||
25EDFCE3161538F6008BAA1D /* RKObjectManagerTest.m in Sources */,
|
||||
2564E40B16173F7B00C12D7D /* RKRelationshipConnectionOperationTest.m in Sources */,
|
||||
25CC5C59161DDADD0008BD21 /* RKResponseDescriptorTest.m in Sources */,
|
||||
25CDA0E7161E828D00F583F3 /* RKISODateFormatterTest.m in Sources */,
|
||||
25BB392E161F4FD700E5C72A /* RKPathUtilitiesTest.m in Sources */,
|
||||
25565965161FDD8800F5BB20 /* RKResponseMapperOperationTest.m in Sources */,
|
||||
@@ -2348,6 +2366,9 @@
|
||||
2506759F162DEA25003210B0 /* RKEntityMappingTest.m in Sources */,
|
||||
2548AC6D162F5E00009E79BF /* RKManagedObjectRequestOperationTest.m in Sources */,
|
||||
255F87911656B22D00914D57 /* RKPaginatorTest.m in Sources */,
|
||||
25E88C8E165C87FF0042ABD0 /* RKEntityIdentifierTest.m in Sources */,
|
||||
2546A95816628EDD0078E044 /* RKConnectionDescriptionTest.m in Sources */,
|
||||
2543A25D1664FD3100821D5B /* RKResponseDescriptorTest.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -2355,7 +2376,6 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
25AE61DE15ADEF5800B319C8 /* RKConnectionMapping.m in Sources */,
|
||||
25160EE51456532C0060A5C5 /* lcl_RK.m in Sources */,
|
||||
25160EFB1456532C0060A5C5 /* LCLNSLog_RK.m in Sources */,
|
||||
25160F0B1456532C0060A5C5 /* SOCKit.m in Sources */,
|
||||
@@ -2389,7 +2409,6 @@
|
||||
25EC1A4014F72B3300C3CF3F /* RKInMemoryManagedObjectCache.m in Sources */,
|
||||
257ABAB315112DD500CCAA76 /* NSManagedObjectContext+RKAdditions.m in Sources */,
|
||||
257ABAB91511371E00CCAA76 /* NSManagedObject+RKAdditions.m in Sources */,
|
||||
25079C72151B93DB00266AE7 /* NSEntityDescription+RKAdditions.m in Sources */,
|
||||
25C954A815542A47005C9E08 /* RKTestConstants.m in Sources */,
|
||||
259D98571550C69A008C90F5 /* RKEntityByAttributeCache.m in Sources */,
|
||||
259D9861155218E5008C90F5 /* RKEntityCache.m in Sources */,
|
||||
@@ -2398,7 +2417,7 @@
|
||||
25FBB855159272DD00955D27 /* RKRouter.m in Sources */,
|
||||
258EA4AB15A38BC0007E07A6 /* RKObjectMappingOperationDataSource.m in Sources */,
|
||||
25AA23D115AF2920006EF62D /* RKManagedObjectMappingOperationDataSource.m in Sources */,
|
||||
2597F99F15AF6DC400E547D7 /* RKRelationshipConnectionOperation.m in Sources */,
|
||||
2597F99F15AF6DC400E547D7 /* RKConnectionOperation.m in Sources */,
|
||||
25104F2215C30CD900829135 /* RKSearchWord.m in Sources */,
|
||||
25104F2C15C30D1700829135 /* RKManagedObjectStore+RKSearchAdditions.m in Sources */,
|
||||
25104F3215C30E7400829135 /* RKSearchIndexer.m in Sources */,
|
||||
@@ -2433,6 +2452,9 @@
|
||||
25A226D91618A57500952D72 /* RKObjectUtilities.m in Sources */,
|
||||
2507C32A161BD5C700EA71FF /* RKTestHelpers.m in Sources */,
|
||||
25CDA0DF161E7ED400F583F3 /* RKISO8601DateFormatter.m in Sources */,
|
||||
25E88C85165C5B580042ABD0 /* RKEntityIdentifier.m in Sources */,
|
||||
25E88C8B165C5CC30042ABD0 /* RKConnectionDescription.m in Sources */,
|
||||
25019498166406E30081D68A /* RKValueTransformers.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -2469,7 +2491,6 @@
|
||||
25B6E9E014CF912500B1E881 /* RKTestUser.m in Sources */,
|
||||
252EFAFB14D8EAEC004863C8 /* RKEvent.m in Sources */,
|
||||
25E36E0315195CED00F9E448 /* RKFetchRequestMappingCacheTest.m in Sources */,
|
||||
25079C77151B952200266AE7 /* NSEntityDescription+RKAdditionsTest.m in Sources */,
|
||||
25DB7509151BD551009F01AF /* NSManagedObjectContext+RKAdditionsTest.m in Sources */,
|
||||
259D985B1550C6BE008C90F5 /* RKEntityByAttributeCacheTest.m in Sources */,
|
||||
259D986515521B20008C90F5 /* RKEntityCacheTest.m in Sources */,
|
||||
@@ -2485,7 +2506,6 @@
|
||||
5C927E151608FFFD00DC8B07 /* RKDictionaryUtilitiesTest.m in Sources */,
|
||||
25EDFCE5161538F8008BAA1D /* RKObjectManagerTest.m in Sources */,
|
||||
2564E40C16173F7B00C12D7D /* RKRelationshipConnectionOperationTest.m in Sources */,
|
||||
25CC5C5A161DDADD0008BD21 /* RKResponseDescriptorTest.m in Sources */,
|
||||
25CDA0E8161E828E00F583F3 /* RKISODateFormatterTest.m in Sources */,
|
||||
25BB392F161F4FD700E5C72A /* RKPathUtilitiesTest.m in Sources */,
|
||||
25565966161FDD8800F5BB20 /* RKResponseMapperOperationTest.m in Sources */,
|
||||
@@ -2495,6 +2515,9 @@
|
||||
250675A1162DEA27003210B0 /* RKEntityMappingTest.m in Sources */,
|
||||
2548AC6E162F5E00009E79BF /* RKManagedObjectRequestOperationTest.m in Sources */,
|
||||
255F87921656B22F00914D57 /* RKPaginatorTest.m in Sources */,
|
||||
25E88C8F165C87FF0042ABD0 /* RKEntityIdentifierTest.m in Sources */,
|
||||
2546A95916628EDD0078E044 /* RKConnectionDescriptionTest.m in Sources */,
|
||||
2543A25E1664FD3200821D5B /* RKResponseDescriptorTest.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -2521,6 +2544,7 @@
|
||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
@@ -2549,6 +2573,7 @@
|
||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
@@ -2602,13 +2627,23 @@
|
||||
};
|
||||
25160D3E14564E820060A5C5 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = C87136726FCA44FBBC18C515 /* Pods.xcconfig */;
|
||||
baseConfigurationReference = 964648386780496FA49D3DD6 /* Pods.xcconfig */;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"\"$(SDKROOT)/Developer/Library/Frameworks\"",
|
||||
"\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"",
|
||||
);
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "Code/Support/RestKit-Prefix.pch";
|
||||
INFOPLIST_FILE = "Resources/PLISTs/RestKitTests-Info.plist";
|
||||
OBJROOT = "$(SRCROOT)/Build";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-framework",
|
||||
SenTestingKit,
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SYMROOT = "$(SRCROOT)/Build/Products";
|
||||
WRAPPER_EXTENSION = octest;
|
||||
@@ -2617,13 +2652,23 @@
|
||||
};
|
||||
25160D3F14564E820060A5C5 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = C87136726FCA44FBBC18C515 /* Pods.xcconfig */;
|
||||
baseConfigurationReference = 964648386780496FA49D3DD6 /* Pods.xcconfig */;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"\"$(SDKROOT)/Developer/Library/Frameworks\"",
|
||||
"\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"",
|
||||
);
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "Code/Support/RestKit-Prefix.pch";
|
||||
INFOPLIST_FILE = "Resources/PLISTs/RestKitTests-Info.plist";
|
||||
OBJROOT = "$(SRCROOT)/Build";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-framework",
|
||||
SenTestingKit,
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SYMROOT = "$(SRCROOT)/Build/Products";
|
||||
WRAPPER_EXTENSION = octest;
|
||||
@@ -2688,11 +2733,16 @@
|
||||
};
|
||||
25160E8B145651060060A5C5 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = C87136726FCA44FBBC18C515 /* Pods.xcconfig */;
|
||||
baseConfigurationReference = 92A418BC16A64A74BF92549F /* Pods.xcconfig */;
|
||||
buildSettings = {
|
||||
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"\"$(SDKROOT)/Developer/Library/Frameworks\"",
|
||||
"\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"",
|
||||
);
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "Code/Support/RestKit-Prefix.pch";
|
||||
@@ -2708,12 +2758,17 @@
|
||||
};
|
||||
25160E8C145651060060A5C5 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = C87136726FCA44FBBC18C515 /* Pods.xcconfig */;
|
||||
baseConfigurationReference = 92A418BC16A64A74BF92549F /* Pods.xcconfig */;
|
||||
buildSettings = {
|
||||
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"\"$(SDKROOT)/Developer/Library/Frameworks\"",
|
||||
"\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"",
|
||||
);
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "Code/Support/RestKit-Prefix.pch";
|
||||
|
||||
86
Tests/Logic/CoreData/RKConnectionDescriptionTest.m
Normal file
86
Tests/Logic/CoreData/RKConnectionDescriptionTest.m
Normal file
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// RKConnectionDescriptionTest.m
|
||||
// RestKit
|
||||
//
|
||||
// Created by Blake Watters on 11/25/12.
|
||||
// Copyright (c) 2012 RestKit. All rights reserved.
|
||||
//
|
||||
|
||||
#import "RKTestEnvironment.h"
|
||||
#import "RKConnectionDescription.h"
|
||||
|
||||
@interface RKConnectionDescriptionTest : RKTestCase
|
||||
@property (nonatomic, strong) NSRelationshipDescription *relationship;
|
||||
@end
|
||||
|
||||
@implementation RKConnectionDescriptionTest
|
||||
|
||||
- (void)expectBlock:(void (^)(void))block toRaise:(NSString *)exceptionName reason:(NSString *)reason
|
||||
{
|
||||
NSException *caughtException = nil;
|
||||
@try {
|
||||
block();
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
caughtException = exception;
|
||||
}
|
||||
@finally {
|
||||
expect(caughtException).notTo.beNil();
|
||||
if (caughtException) {
|
||||
if (exceptionName) expect([caughtException name]).to.equal(exceptionName);
|
||||
if (reason) expect([caughtException reason]).to.equal(reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
[RKTestFactory setUp];
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
self.relationship = [entity relationshipsByName][@"cats"];
|
||||
}
|
||||
|
||||
- (void)tearDown
|
||||
{
|
||||
[RKTestFactory tearDown];
|
||||
}
|
||||
|
||||
- (void)testInitWithNilRelationshipRaisesError
|
||||
{
|
||||
expect(^{ RKConnectionDescription __unused *connection = [[RKConnectionDescription alloc] initWithRelationship:nil attributes:@{ @"catID": @"catID" }]; }).to.raiseWithReason(NSInternalInconsistencyException, @"Invalid parameter not satisfying: relationship");
|
||||
}
|
||||
|
||||
- (void)testInitWithNilAttributesRaisesError
|
||||
{
|
||||
// expect(^{ RKConnectionDescription __unused *connection = [[RKConnectionDescription alloc] initWithRelationship:self.relationship attributes:@"Invalid parameter not satisfying: attributes"]; }).to.raise(NSInternalInconsistencyException);
|
||||
[self expectBlock:^{
|
||||
RKConnectionDescription __unused *connection = [[RKConnectionDescription alloc] initWithRelationship:self.relationship attributes:nil];
|
||||
} toRaise:NSInternalInconsistencyException reason:@"Invalid parameter not satisfying: attributes"];
|
||||
}
|
||||
|
||||
- (void)testInitWithEmptyAttributesDictionaryRaisesError
|
||||
{
|
||||
// expect(^{ RKConnectionDescription __unused *connection = [[RKConnectionDescription alloc] initWithRelationship:self.relationship attributes:@{}]; }).to.raiseWithReason(NSInternalInconsistencyException, @"Cannot connect a relationship without at least one pair of attributes describing the connection");
|
||||
[self expectBlock:^{
|
||||
RKConnectionDescription __unused *connection = [[RKConnectionDescription alloc] initWithRelationship:self.relationship attributes:@{}];
|
||||
} toRaise:NSInternalInconsistencyException reason:@"Cannot connect a relationship without at least one pair of attributes describing the connection"];
|
||||
}
|
||||
|
||||
- (void)testInitWithAttributeThatDoesNotExistInEntityRaisesError
|
||||
{
|
||||
// expect(^{ RKConnectionDescription __unused *connection = [[RKConnectionDescription alloc] initWithRelationship:self.relationship attributes:@{ @"invalidID": @"catID" }]; }).to.raiseWithReason(NSInternalInconsistencyException, @"Invalid parameter not satisfying: relationship");
|
||||
[self expectBlock:^{
|
||||
RKConnectionDescription __unused *connection = [[RKConnectionDescription alloc] initWithRelationship:self.relationship attributes:@{ @"invalidID": @"catID" }];
|
||||
} toRaise:NSInternalInconsistencyException reason:@"Cannot connect relationship: invalid attributes given for source entity 'Human': invalidID"];
|
||||
}
|
||||
|
||||
- (void)testInitWithAttributeThatDoesNotExistInDestinationEntityRaisesError
|
||||
{
|
||||
// expect(^{ RKConnectionDescription __unused *connection = [[RKConnectionDescription alloc] initWithRelationship:self.relationship attributes:@{ @"favoriteCatID": @"invalid" }]; }).to.raiseWithReason(NSInternalInconsistencyException, @"Invalid parameter not satisfying: relationship");
|
||||
[self expectBlock:^{
|
||||
RKConnectionDescription __unused *connection = [[RKConnectionDescription alloc] initWithRelationship:self.relationship attributes:@{ @"favoriteCatID": @"invalid" }];
|
||||
} toRaise:NSInternalInconsistencyException reason:@"Cannot connect relationship: invalid attributes given for destination entity 'Cat': invalid"];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Human" inManagedObjectContext:self.managedObjectContext];
|
||||
self.cache = [[RKEntityByAttributeCache alloc] initWithEntity:entity
|
||||
attribute:@"railsID"
|
||||
attributes:@[ @"railsID" ]
|
||||
managedObjectContext:self.managedObjectContext];
|
||||
// Disable cache monitoring. Tested in specific cases.
|
||||
self.cache.monitorsContextForChanges = NO;
|
||||
@@ -61,7 +61,7 @@
|
||||
|
||||
- (void)testAttributeNameIsAssigned
|
||||
{
|
||||
assertThat(self.cache.attribute, is(equalTo(@"railsID")));
|
||||
assertThat(self.cache.attributes, is(equalTo(@[ @"railsID" ])));
|
||||
}
|
||||
|
||||
#pragma mark - Loading and Flushing
|
||||
@@ -124,7 +124,7 @@
|
||||
|
||||
NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
|
||||
childContext.parentContext = self.managedObjectContext;
|
||||
NSManagedObject *object = [self.cache objectWithAttributeValue:[NSNumber numberWithInteger:12345] inContext:childContext];
|
||||
NSManagedObject *object = [self.cache objectWithAttributeValues:@{ @"railsID": @12345 } inContext:childContext];
|
||||
assertThat(object.objectID, is(equalTo(human.objectID)));
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
|
||||
NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
|
||||
childContext.parentContext = self.managedObjectContext;
|
||||
NSManagedObject *object = [self.cache objectWithAttributeValue:@"12345" inContext:childContext];
|
||||
NSManagedObject *object = [self.cache objectWithAttributeValues:@{ @"railsID": @"12345" } inContext:childContext];
|
||||
assertThat(object, is(notNilValue()));
|
||||
assertThat(object.objectID, is(equalTo(human.objectID)));
|
||||
}
|
||||
@@ -155,7 +155,7 @@
|
||||
|
||||
NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
|
||||
childContext.parentContext = self.managedObjectContext;
|
||||
NSArray *objects = [self.cache objectsWithAttributeValue:[NSNumber numberWithInt:12345] inContext:childContext];
|
||||
NSArray *objects = [self.cache objectsWithAttributeValues:@{ @"railsID": @(12345) } inContext:childContext];
|
||||
assertThat(objects, hasCountOf(2));
|
||||
assertThat([objects objectAtIndex:0], is(instanceOf([NSManagedObject class])));
|
||||
}
|
||||
@@ -241,7 +241,7 @@
|
||||
[self.managedObjectStore.persistentStoreManagedObjectContext save:nil];
|
||||
|
||||
[self.cache addObject:human];
|
||||
assertThatBool([self.cache containsObjectWithAttributeValue:[NSNumber numberWithInteger:12345]], is(equalToBool(YES)));
|
||||
assertThatBool([self.cache containsObjectWithAttributeValues:@{ @"railsID": @(12345) }], is(equalToBool(YES)));
|
||||
}
|
||||
|
||||
- (void)testCount
|
||||
@@ -286,7 +286,7 @@
|
||||
|
||||
[self.cache addObject:human1];
|
||||
[self.cache addObject:human2];
|
||||
assertThatInteger([self.cache countWithAttributeValue:[NSNumber numberWithInteger:12345]], is(equalToInteger(2)));
|
||||
assertThatInteger([self.cache countWithAttributeValues:@{ @"railsID": @(12345) }], is(equalToInteger(2)));
|
||||
}
|
||||
|
||||
- (void)testThatUnloadedCacheReturnsCountOfZero
|
||||
@@ -388,4 +388,12 @@
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Compound Key Tests
|
||||
|
||||
// missing attributes
|
||||
// padding nil
|
||||
// trying to look-up by nil
|
||||
// trying to lookup with empty dictionary
|
||||
// using weird attribute types as cache keys
|
||||
|
||||
@end
|
||||
|
||||
@@ -47,21 +47,21 @@
|
||||
|
||||
- (void)testIsEntityCachedByAttribute
|
||||
{
|
||||
assertThatBool([_cache isEntity:self.entity cachedByAttribute:@"railsID"], is(equalToBool(NO)));
|
||||
[_cache cacheObjectsForEntity:self.entity byAttribute:@"railsID"];
|
||||
assertThatBool([_cache isEntity:self.entity cachedByAttribute:@"railsID"], is(equalToBool(YES)));
|
||||
assertThatBool([_cache isEntity:self.entity cachedByAttributes:@[ @"railsID" ]], is(equalToBool(NO)));
|
||||
[_cache cacheObjectsForEntity:self.entity byAttributes:@[ @"railsID" ]];
|
||||
assertThatBool([_cache isEntity:self.entity cachedByAttributes:@[ @"railsID" ]], is(equalToBool(YES)));
|
||||
}
|
||||
|
||||
- (void)testRetrievalOfUnderlyingEntityAttributeCache
|
||||
{
|
||||
[_cache cacheObjectsForEntity:self.entity byAttribute:@"railsID"];
|
||||
RKEntityByAttributeCache *attributeCache = [_cache attributeCacheForEntity:self.entity attribute:@"railsID"];
|
||||
[_cache cacheObjectsForEntity:self.entity byAttributes:@[ @"railsID" ]];
|
||||
RKEntityByAttributeCache *attributeCache = [_cache attributeCacheForEntity:self.entity attributes:@[ @"railsID" ]];
|
||||
assertThat(attributeCache, is(notNilValue()));
|
||||
}
|
||||
|
||||
- (void)testRetrievalOfUnderlyingEntityAttributeCaches
|
||||
{
|
||||
[_cache cacheObjectsForEntity:self.entity byAttribute:@"railsID"];
|
||||
[_cache cacheObjectsForEntity:self.entity byAttributes:@[ @"railsID" ]];
|
||||
NSArray *caches = [_cache attributeCachesForEntity:self.entity];
|
||||
assertThat(caches, is(notNilValue()));
|
||||
assertThatInteger([caches count], is(equalToInteger(1)));
|
||||
@@ -74,10 +74,10 @@
|
||||
NSError *error = nil;
|
||||
[self.managedObjectStore.persistentStoreManagedObjectContext save:&error];
|
||||
|
||||
[_cache cacheObjectsForEntity:self.entity byAttribute:@"railsID"];
|
||||
[_cache cacheObjectsForEntity:self.entity byAttributes:@[ @"railsID" ]];
|
||||
NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
|
||||
childContext.parentContext = self.managedObjectStore.persistentStoreManagedObjectContext;
|
||||
NSManagedObject *fetchedObject = [self.cache objectForEntity:self.entity withAttribute:@"railsID" value:[NSNumber numberWithInteger:12345] inContext:childContext];
|
||||
NSManagedObject *fetchedObject = [self.cache objectForEntity:self.entity withAttributeValues:@{ @"railsID": @(12345) } inContext:childContext];
|
||||
assertThat(fetchedObject, is(notNilValue()));
|
||||
}
|
||||
|
||||
@@ -90,10 +90,10 @@
|
||||
NSError *error = nil;
|
||||
[self.managedObjectStore.persistentStoreManagedObjectContext save:&error];
|
||||
|
||||
[_cache cacheObjectsForEntity:self.entity byAttribute:@"railsID"];
|
||||
[_cache cacheObjectsForEntity:self.entity byAttributes:@[ @"railsID" ]];
|
||||
NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
|
||||
childContext.parentContext = self.managedObjectStore.persistentStoreManagedObjectContext;
|
||||
NSArray *objects = [self.cache objectsForEntity:self.entity withAttribute:@"railsID" value:[NSNumber numberWithInteger:12345] inContext:childContext];
|
||||
NSArray *objects = [self.cache objectsForEntity:self.entity withAttributeValues:@{ @"railsID": @(12345) } inContext:childContext];
|
||||
assertThat(objects, hasCountOf(2));
|
||||
assertThat([objects valueForKey:@"objectID"], containsInAnyOrder(human1.objectID, human2.objectID, nil));
|
||||
}
|
||||
@@ -108,31 +108,31 @@
|
||||
human2.name = @"Sarah";
|
||||
|
||||
[self.managedObjectStore.persistentStoreManagedObjectContext save:nil];
|
||||
[_cache cacheObjectsForEntity:self.entity byAttribute:@"railsID"];
|
||||
[_cache cacheObjectsForEntity:self.entity byAttribute:@"name"];
|
||||
[_cache cacheObjectsForEntity:self.entity byAttributes:@[ @"railsID" ]];
|
||||
[_cache cacheObjectsForEntity:self.entity byAttributes:@[ @"name" ]];
|
||||
|
||||
NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
|
||||
childContext.parentContext = self.managedObjectStore.persistentStoreManagedObjectContext;
|
||||
|
||||
NSArray *objects = [self.cache objectsForEntity:self.entity withAttribute:@"railsID" value:[NSNumber numberWithInteger:12345] inContext:childContext];
|
||||
NSArray *objects = [self.cache objectsForEntity:self.entity withAttributeValues:@{ @"railsID": @(12345) } inContext:childContext];
|
||||
assertThat(objects, hasCountOf(2));
|
||||
assertThat([objects valueForKey:@"objectID"], containsInAnyOrder(human1.objectID, human2.objectID, nil));
|
||||
|
||||
objects = [self.cache objectsForEntity:self.entity withAttribute:@"name" value:@"Blake" inContext:childContext];
|
||||
objects = [self.cache objectsForEntity:self.entity withAttributeValues:@{ @"name": @"Blake" } inContext:childContext];
|
||||
assertThat(objects, hasCountOf(1));
|
||||
assertThat([objects valueForKey:@"objectID"], contains(human1.objectID, nil));
|
||||
|
||||
[self.cache flush];
|
||||
objects = [self.cache objectsForEntity:self.entity withAttribute:@"railsID" value:[NSNumber numberWithInteger:12345] inContext:childContext];
|
||||
objects = [self.cache objectsForEntity:self.entity withAttributeValues:@{ @"railsID": @(12345) } inContext:childContext];
|
||||
assertThat(objects, is(empty()));
|
||||
objects = [self.cache objectsForEntity:self.entity withAttribute:@"name" value:@"Blake" inContext:childContext];
|
||||
objects = [self.cache objectsForEntity:self.entity withAttributeValues:@{ @"name": @"Blake" } inContext:childContext];
|
||||
assertThat(objects, is(empty()));
|
||||
}
|
||||
|
||||
- (void)testAddingObjectAddsToEachUnderlyingEntityAttributeCaches
|
||||
{
|
||||
[_cache cacheObjectsForEntity:self.entity byAttribute:@"railsID"];
|
||||
[_cache cacheObjectsForEntity:self.entity byAttribute:@"name"];
|
||||
[_cache cacheObjectsForEntity:self.entity byAttributes:@[ @"railsID" ]];
|
||||
[_cache cacheObjectsForEntity:self.entity byAttributes:@[ @"name" ]];
|
||||
|
||||
RKHuman *human1 = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:self.managedObjectStore.persistentStoreManagedObjectContext];
|
||||
human1.railsID = [NSNumber numberWithInteger:12345];
|
||||
@@ -154,19 +154,19 @@
|
||||
NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
|
||||
childContext.parentContext = self.managedObjectStore.persistentStoreManagedObjectContext;
|
||||
|
||||
NSArray *objects = [self.cache objectsForEntity:self.entity withAttribute:@"railsID" value:[NSNumber numberWithInteger:12345] inContext:childContext];
|
||||
NSArray *objects = [self.cache objectsForEntity:self.entity withAttributeValues:@{ @"railsID": @(12345) } inContext:childContext];
|
||||
assertThat(objects, hasCountOf(2));
|
||||
assertThat([objects valueForKey:@"objectID"], containsInAnyOrder(human1.objectID, human2.objectID, nil));
|
||||
|
||||
objects = [self.cache objectsForEntity:self.entity withAttribute:@"name" value:@"Blake" inContext:childContext];
|
||||
objects = [self.cache objectsForEntity:self.entity withAttributeValues:@{ @"name": @"Blake" } inContext:childContext];
|
||||
assertThat(objects, hasCountOf(1));
|
||||
assertThat([objects valueForKey:@"objectID"], contains(human1.objectID, nil));
|
||||
}
|
||||
|
||||
- (void)testRemovingObjectRemovesFromUnderlyingEntityAttributeCaches
|
||||
{
|
||||
[_cache cacheObjectsForEntity:self.entity byAttribute:@"railsID"];
|
||||
[_cache cacheObjectsForEntity:self.entity byAttribute:@"name"];
|
||||
[_cache cacheObjectsForEntity:self.entity byAttributes:@[ @"railsID" ]];
|
||||
[_cache cacheObjectsForEntity:self.entity byAttributes:@[ @"name" ]];
|
||||
|
||||
RKHuman *human1 = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:self.managedObjectStore.persistentStoreManagedObjectContext];
|
||||
human1.railsID = [NSNumber numberWithInteger:12345];
|
||||
@@ -188,11 +188,11 @@
|
||||
NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
|
||||
childContext.parentContext = self.managedObjectStore.persistentStoreManagedObjectContext;
|
||||
|
||||
NSArray *objects = [self.cache objectsForEntity:self.entity withAttribute:@"railsID" value:[NSNumber numberWithInteger:12345] inContext:childContext];
|
||||
NSArray *objects = [self.cache objectsForEntity:self.entity withAttributeValues:@{ @"railsID": @(12345) } inContext:childContext];
|
||||
assertThat(objects, hasCountOf(2));
|
||||
assertThat([objects valueForKey:@"objectID"], containsInAnyOrder(human1.objectID, human2.objectID, nil));
|
||||
|
||||
RKEntityByAttributeCache *entityAttributeCache = [self.cache attributeCacheForEntity:self.entity attribute:@"railsID"];
|
||||
RKEntityByAttributeCache *entityAttributeCache = [self.cache attributeCacheForEntity:self.entity attributes:@[ @"railsID" ]];
|
||||
assertThatBool([entityAttributeCache containsObject:human1], is(equalToBool(YES)));
|
||||
[self.cache removeObject:human1];
|
||||
assertThatBool([entityAttributeCache containsObject:human1], is(equalToBool(NO)));
|
||||
|
||||
225
Tests/Logic/CoreData/RKEntityIdentifierTest.m
Normal file
225
Tests/Logic/CoreData/RKEntityIdentifierTest.m
Normal file
@@ -0,0 +1,225 @@
|
||||
//
|
||||
// RKEntityIndexTest.m
|
||||
// RestKit
|
||||
//
|
||||
// Created by Blake Watters on 11/20/12.
|
||||
// Copyright (c) 2012 RestKit. All rights reserved.
|
||||
//
|
||||
|
||||
#import "RKTestEnvironment.h"
|
||||
#import "RKEntityIdentifier.h"
|
||||
|
||||
@interface RKEntityIdentifierTest : RKTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation RKEntityIdentifierTest
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
[RKTestFactory setUp];
|
||||
}
|
||||
|
||||
- (void)testThatInitEntityIdentifierWithNilAttributesRaisesException
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Human" inManagedObjectContext:managedObjectStore.mainQueueManagedObjectContext];
|
||||
NSException *expectedExcepetion = nil;
|
||||
@try {
|
||||
RKEntityIdentifier *entityIdentifier __unused = [[RKEntityIdentifier alloc] initWithEntity:entity attributes:nil];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
expectedExcepetion = exception;
|
||||
}
|
||||
expect(expectedExcepetion).notTo.beNil();
|
||||
expect([expectedExcepetion description]).to.equal(@"Invalid parameter not satisfying: attributes");
|
||||
}
|
||||
|
||||
- (void)testThatInitEntityIdentifierWithEmptyAttributesRaisesException
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Human" inManagedObjectContext:managedObjectStore.mainQueueManagedObjectContext];
|
||||
NSException *expectedExcepetion = nil;
|
||||
@try {
|
||||
RKEntityIdentifier *entityIdentifier __unused = [[RKEntityIdentifier alloc] initWithEntity:entity attributes:@[]];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
expectedExcepetion = exception;
|
||||
}
|
||||
expect(expectedExcepetion).notTo.beNil();
|
||||
expect([expectedExcepetion description]).to.equal(@"At least one attribute must be provided to identify managed objects");
|
||||
}
|
||||
|
||||
- (void)testThatInitWithInvalidEntityNameRaisesError
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
NSException *expectedExcepetion = nil;
|
||||
@try {
|
||||
RKEntityIdentifier *entityIdentifier __unused = [RKEntityIdentifier identifierWithEntityName:@"Invalid" attributes:nil inManagedObjectStore:managedObjectStore];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
expectedExcepetion = exception;
|
||||
}
|
||||
expect(expectedExcepetion).notTo.beNil();
|
||||
expect([expectedExcepetion description]).to.equal(@"Invalid parameter not satisfying: entity");
|
||||
}
|
||||
|
||||
- (void)testInitializingEntityIdentifierByName
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
NSAttributeDescription *railsIDAttribute = entity.attributesByName[@"railsID"];
|
||||
RKEntityIdentifier *entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
expect(entityIdentifier.entity).to.equal(entity);
|
||||
NSArray *attributes = @[ railsIDAttribute ];
|
||||
expect(entityIdentifier.attributes).equal(attributes);
|
||||
}
|
||||
|
||||
#pragma mark - Entity Identifier Inference
|
||||
|
||||
// TODO: The attributes to auto-detect: entityNameID, ID, identififer, url, URL
|
||||
|
||||
- (void)testEntityIdentifierInferenceForEntityWithLlamaCasedIDAttribute
|
||||
{
|
||||
NSEntityDescription *entity = [[NSEntityDescription alloc] init];
|
||||
[entity setName:@"Monkey"];
|
||||
NSAttributeDescription *identifierAttribute = [NSAttributeDescription new];
|
||||
[identifierAttribute setName:@"monkeyID"];
|
||||
[entity setProperties:@[ identifierAttribute ]];
|
||||
RKEntityIdentifier *entityIdentifier = [RKEntityIdentifier inferredIdentifierForEntity:entity];
|
||||
expect(entityIdentifier).notTo.beNil();
|
||||
NSArray *attributeNames = @[ @"monkeyID" ];
|
||||
expect([[entityIdentifier attributes] valueForKey:@"name"]).to.equal(attributeNames);
|
||||
}
|
||||
|
||||
- (void)testEntityIdentifierInferenceForEntityWithIDAttribute
|
||||
{
|
||||
NSEntityDescription *entity = [[NSEntityDescription alloc] init];
|
||||
[entity setName:@"Monkey"];
|
||||
NSAttributeDescription *identifierAttribute = [NSAttributeDescription new];
|
||||
[identifierAttribute setName:@"ID"];
|
||||
[entity setProperties:@[ identifierAttribute ]];
|
||||
RKEntityIdentifier *entityIdentifier = [RKEntityIdentifier inferredIdentifierForEntity:entity];
|
||||
expect(entityIdentifier).notTo.beNil();
|
||||
NSArray *attributeNames = @[ @"ID" ];
|
||||
expect([[entityIdentifier attributes] valueForKey:@"name"]).to.equal(attributeNames);
|
||||
}
|
||||
|
||||
- (void)testEntityIdentifierInferenceForEntityWithIdentifierAttribute
|
||||
{
|
||||
NSEntityDescription *entity = [[NSEntityDescription alloc] init];
|
||||
[entity setName:@"Monkey"];
|
||||
NSAttributeDescription *identifierAttribute = [NSAttributeDescription new];
|
||||
[identifierAttribute setName:@"identifier"];
|
||||
[entity setProperties:@[ identifierAttribute ]];
|
||||
RKEntityIdentifier *entityIdentifier = [RKEntityIdentifier inferredIdentifierForEntity:entity];
|
||||
expect(entityIdentifier).notTo.beNil();
|
||||
NSArray *attributeNames = @[ @"identifier" ];
|
||||
expect([[entityIdentifier attributes] valueForKey:@"name"]).to.equal(attributeNames);
|
||||
}
|
||||
|
||||
- (void)testEntityIdentifierInferenceForEntityWithURLAttribute
|
||||
{
|
||||
NSEntityDescription *entity = [[NSEntityDescription alloc] init];
|
||||
[entity setName:@"Monkey"];
|
||||
NSAttributeDescription *identifierAttribute = [NSAttributeDescription new];
|
||||
[identifierAttribute setName:@"URL"];
|
||||
[entity setProperties:@[ identifierAttribute ]];
|
||||
RKEntityIdentifier *entityIdentifier = [RKEntityIdentifier inferredIdentifierForEntity:entity];
|
||||
expect(entityIdentifier).notTo.beNil();
|
||||
NSArray *attributeNames = @[ @"URL" ];
|
||||
expect([[entityIdentifier attributes] valueForKey:@"name"]).to.equal(attributeNames);
|
||||
}
|
||||
|
||||
- (void)testEntityIdentifierInferenceForEntityWithUrlAttribute
|
||||
{
|
||||
NSEntityDescription *entity = [[NSEntityDescription alloc] init];
|
||||
[entity setName:@"Monkey"];
|
||||
NSAttributeDescription *identifierAttribute = [NSAttributeDescription new];
|
||||
[identifierAttribute setName:@"url"];
|
||||
[entity setProperties:@[ identifierAttribute ]];
|
||||
RKEntityIdentifier *entityIdentifier = [RKEntityIdentifier inferredIdentifierForEntity:entity];
|
||||
expect(entityIdentifier).notTo.beNil();
|
||||
NSArray *attributeNames = @[ @"url" ];
|
||||
expect([[entityIdentifier attributes] valueForKey:@"name"]).to.equal(attributeNames);
|
||||
}
|
||||
|
||||
- (void)testEntityIdentifierInferenceFromUserInfoKeyForSingleValue
|
||||
{
|
||||
NSEntityDescription *entity = [[NSEntityDescription alloc] init];
|
||||
[entity setName:@"Monkey"];
|
||||
NSAttributeDescription *identifierAttribute = [NSAttributeDescription new];
|
||||
[identifierAttribute setName:@"monkeyID"]; // We ignore this by specifying the userInfo key
|
||||
NSAttributeDescription *nameAttribute = [NSAttributeDescription new];
|
||||
[nameAttribute setName:@"name"];
|
||||
[entity setProperties:@[ identifierAttribute, nameAttribute ]];
|
||||
[entity setUserInfo:@{ RKEntityIdentifierUserInfoKey: @"name" }];
|
||||
RKEntityIdentifier *entityIdentifier = [RKEntityIdentifier inferredIdentifierForEntity:entity];
|
||||
expect(entityIdentifier).notTo.beNil();
|
||||
NSArray *attributeNames = @[ @"name" ];
|
||||
expect([[entityIdentifier attributes] valueForKey:@"name"]).to.equal(attributeNames);
|
||||
}
|
||||
|
||||
- (void)testEntityIdentifierInferenceFromUserInfoKeyForArrayOfValues
|
||||
{
|
||||
NSEntityDescription *entity = [[NSEntityDescription alloc] init];
|
||||
[entity setName:@"Monkey"];
|
||||
NSAttributeDescription *identifierAttribute = [NSAttributeDescription new];
|
||||
[identifierAttribute setName:@"monkeyID"];
|
||||
NSAttributeDescription *nameAttribute = [NSAttributeDescription new];
|
||||
[nameAttribute setName:@"name"];
|
||||
[entity setProperties:@[ identifierAttribute, nameAttribute ]];
|
||||
[entity setUserInfo:@{ RKEntityIdentifierUserInfoKey: @[ @"name", @"monkeyID" ] }];
|
||||
RKEntityIdentifier *entityIdentifier = [RKEntityIdentifier inferredIdentifierForEntity:entity];
|
||||
expect(entityIdentifier).notTo.beNil();
|
||||
NSArray *attributeNames = @[ @"name", @"monkeyID" ];
|
||||
expect([[entityIdentifier attributes] valueForKey:@"name"]).to.equal(attributeNames);
|
||||
}
|
||||
|
||||
- (void)testEntityIdentifierInferenceFromUserInfoKeyRaisesErrorForInvalidValue
|
||||
{
|
||||
NSEntityDescription *entity = [[NSEntityDescription alloc] init];
|
||||
[entity setName:@"Monkey"];
|
||||
NSAttributeDescription *identifierAttribute = [NSAttributeDescription new];
|
||||
[identifierAttribute setName:@"monkeyID"];
|
||||
NSAttributeDescription *nameAttribute = [NSAttributeDescription new];
|
||||
[nameAttribute setName:@"name"];
|
||||
[entity setProperties:@[ identifierAttribute, nameAttribute ]];
|
||||
[entity setUserInfo:@{ RKEntityIdentifierUserInfoKey: @(12345) }];
|
||||
|
||||
NSException *caughtException = nil;
|
||||
@try {
|
||||
RKEntityIdentifier __unused *entityIdentifier = [RKEntityIdentifier inferredIdentifierForEntity:entity];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
caughtException = exception;
|
||||
}
|
||||
@finally {
|
||||
expect([caughtException name]).to.equal(NSInvalidArgumentException);
|
||||
expect([caughtException reason]).to.equal(@"Invalid value given in user info key 'RKEntityIdentifierAttributes' of entity 'Monkey': expected an `NSString` or `NSArray` of strings, instead got '12345' (__NSCFNumber)");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testEntityIdentifierInferenceFromUserInfoKeyRaisesErrorForNonexistantAttributeName
|
||||
{
|
||||
NSEntityDescription *entity = [[NSEntityDescription alloc] init];
|
||||
[entity setName:@"Monkey"];
|
||||
NSAttributeDescription *identifierAttribute = [NSAttributeDescription new];
|
||||
[identifierAttribute setName:@"monkeyID"];
|
||||
[entity setProperties:@[ identifierAttribute ]];
|
||||
[entity setUserInfo:@{ RKEntityIdentifierUserInfoKey: @"nonExistant" }];
|
||||
|
||||
NSException *caughtException = nil;
|
||||
@try {
|
||||
RKEntityIdentifier __unused *entityIdentifier = [RKEntityIdentifier inferredIdentifierForEntity:entity];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
caughtException = exception;
|
||||
}
|
||||
@finally {
|
||||
expect([caughtException name]).to.equal(NSInvalidArgumentException);
|
||||
expect([caughtException reason]).to.equal(@"Invalid identifier attribute specified in user info key 'RKEntityIdentifierAttributes' of entity 'Monkey': no attribue was found with the name 'nonExistant'");
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -42,6 +42,8 @@
|
||||
- (void)tearDown
|
||||
{
|
||||
[RKTestFactory tearDown];
|
||||
|
||||
[RKEntityMapping setEntityIdentifierInferenceEnabled:YES];
|
||||
}
|
||||
|
||||
- (void)testShouldReturnTheDefaultValueForACoreDataAttribute
|
||||
@@ -50,7 +52,7 @@
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
|
||||
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Cat" inManagedObjectStore:managedObjectStore];
|
||||
id value = [mapping defaultValueForMissingAttribute:@"name"];
|
||||
id value = [mapping defaultValueForAttribute:@"name"];
|
||||
assertThat(value, is(equalTo(@"Kitty Cat!")));
|
||||
}
|
||||
|
||||
@@ -60,22 +62,20 @@
|
||||
managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
mapping.forceCollectionMapping = YES;
|
||||
mapping.primaryKeyAttribute = @"name";
|
||||
[mapping mapKeyOfNestedDictionaryToAttribute:@"name"];
|
||||
mapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"name" ] inManagedObjectStore:managedObjectStore];
|
||||
[mapping addAttributeMappingFromKeyOfRepresentationToAttribute:@"name"];
|
||||
RKAttributeMapping *idMapping = [RKAttributeMapping attributeMappingFromKeyPath:@"(name).id" toKeyPath:@"railsID"];
|
||||
[mapping addPropertyMapping:idMapping];
|
||||
NSMutableDictionary *mappingsDictionary = [NSMutableDictionary dictionary];
|
||||
[mappingsDictionary setObject:mapping forKey:@"users"];
|
||||
|
||||
id mockCacheStrategy = [OCMockObject partialMockForObject:managedObjectStore.managedObjectCache];
|
||||
[[[mockCacheStrategy expect] andForwardToRealObject] findInstanceOfEntity:OCMOCK_ANY
|
||||
withPrimaryKeyAttribute:mapping.primaryKeyAttribute
|
||||
value:@"blake"
|
||||
inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
[[[mockCacheStrategy expect] andForwardToRealObject] findInstanceOfEntity:mapping.entity
|
||||
withPrimaryKeyAttribute:mapping.primaryKeyAttribute
|
||||
value:@"rachit"
|
||||
inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
[[[mockCacheStrategy expect] andForwardToRealObject] managedObjectsWithEntity:OCMOCK_ANY
|
||||
attributeValues:@{ @"name": @"blake" }
|
||||
inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
[[[mockCacheStrategy expect] andForwardToRealObject] managedObjectsWithEntity:OCMOCK_ANY
|
||||
attributeValues:@{ @"name": @"rachit" }
|
||||
inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
id userInfo = [RKTestFixture parsedObjectWithContentsOfFixture:@"DynamicKeys.json"];
|
||||
RKMapperOperation *mapper = [[RKMapperOperation alloc] initWithObject:userInfo mappingsDictionary:mappingsDictionary];
|
||||
RKManagedObjectMappingOperationDataSource *dataSource = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext
|
||||
@@ -90,24 +90,24 @@
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
RKDynamicMapping *dynamicMapping = [RKDynamicMapping new];
|
||||
RKEntityMapping *childMapping = [RKEntityMapping mappingForEntityForName:@"Child" inManagedObjectStore:managedObjectStore];
|
||||
child[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
childMapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Child" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[childMapping addAttributeMappingsFromArray:@[@"name"]];
|
||||
|
||||
RKEntityMapping *parentMapping = [RKEntityMapping mappingForEntityForName:@"Parent" inManagedObjectStore:managedObjectStore];
|
||||
parent[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
parentMapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Parent" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[parentMapping addAttributeMappingsFromArray:@[@"name", @"age"]];
|
||||
|
||||
[dynamicMapping setObjectMapping:parentMapping whenValueOfKeyPath:@"type" isEqualTo:@"Parent"];
|
||||
[dynamicMapping setObjectMapping:childMapping whenValueOfKeyPath:@"type" isEqualTo:@"Child"];
|
||||
|
||||
RKObjectMapping *mapping = [dynamicMapping objectMappingForRepresentation:[RKTestFixture parsedObjectWithContentsOfFixture:@"parent.json"]];
|
||||
assertThat(mapping, is(notNilValue()));
|
||||
assertThatBool([mapping isKindOfClass:[RKEntityMapping class]], is(equalToBool(YES)));
|
||||
assertThat(NSStringFromClass(mapping.objectClass), is(equalTo(@"Parent")));
|
||||
expect(mapping).notTo.beNil();
|
||||
expect([mapping isKindOfClass:[RKEntityMapping class]]).to.equal(YES);
|
||||
expect(NSStringFromClass(mapping.objectClass)).to.equal(@"RKParent");
|
||||
mapping = [dynamicMapping objectMappingForRepresentation:[RKTestFixture parsedObjectWithContentsOfFixture:@"child.json"]];
|
||||
assertThat(mapping, is(notNilValue()));
|
||||
assertThatBool([mapping isKindOfClass:[RKEntityMapping class]], is(equalToBool(YES)));
|
||||
assertThat(NSStringFromClass(mapping.objectClass), is(equalTo(@"Child")));
|
||||
expect(mapping).notTo.beNil();
|
||||
expect([mapping isKindOfClass:[RKEntityMapping class]]).to.equal(YES);
|
||||
expect(NSStringFromClass(mapping.objectClass)).to.equal(@"RKChild");
|
||||
}
|
||||
|
||||
- (void)testShouldIncludeTransformableAttributesInPropertyNamesAndTypes
|
||||
@@ -125,25 +125,6 @@
|
||||
assertThat([propertyNamesAndTypes objectForKey:@"favoriteColors"], is(notNilValue()));
|
||||
}
|
||||
|
||||
- (void)testThatAssigningAnEntityWithANonNilPrimaryKeyAttributeSetsTheDefaultValueForTheMapping
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Cat" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
RKEntityMapping *mapping = [[RKEntityMapping alloc] initWithEntity:entity];
|
||||
assertThat(mapping.primaryKeyAttribute, is(equalTo(@"railsID")));
|
||||
}
|
||||
|
||||
- (void)testThatAssigningAPrimaryKeyAttributeToAMappingWhoseEntityHasANilPrimaryKeyAttributeAssignsItToTheEntity
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Cloud" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
RKEntityMapping *mapping = [[RKEntityMapping alloc] initWithEntity:entity];
|
||||
assertThat(mapping.primaryKeyAttribute, is(nilValue()));
|
||||
mapping.primaryKeyAttribute = @"name";
|
||||
assertThat(entity.primaryKeyAttributeName, is(equalTo(@"name")));
|
||||
assertThat(entity.primaryKeyAttribute, is(notNilValue()));
|
||||
}
|
||||
|
||||
- (void)testThatMappingAnEmptyArrayOnToAnExistingRelationshipDisassociatesTheRelatedObjects
|
||||
{
|
||||
RKHuman *blake = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:nil withProperties:@{ @"name": @"Blake" }];
|
||||
@@ -213,4 +194,156 @@
|
||||
expect(blake.cats).to.beEmpty();
|
||||
}
|
||||
|
||||
- (void)testAssignmentOfEntityIdentifierForIncorrectEntityRaisesException
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
RKEntityMapping *humanEntityMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
RKEntityIdentifier *catIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Cat" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
NSException *expectedException = nil;
|
||||
@try {
|
||||
humanEntityMapping.entityIdentifier = catIdentifier;
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
expectedException = exception;
|
||||
}
|
||||
@finally {
|
||||
expect(expectedException).notTo.beNil();
|
||||
expect([expectedException reason]).to.equal(@"Invalid entity identifier value: The identifier given is for the 'Cat' entity.");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testAddingConnectionByAttributeName
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
RKEntityMapping *humanEntityMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
[humanEntityMapping addConnectionForRelationship:@"favoriteCat" connectedBy:@"favoriteCatID"];
|
||||
RKConnectionDescription *connection = [humanEntityMapping connectionForRelationship:@"favoriteCat"];
|
||||
NSDictionary *expectedAttributes = @{ @"favoriteCatID": @"favoriteCatID" };
|
||||
expect(connection.attributes).to.equal(expectedAttributes);
|
||||
}
|
||||
|
||||
- (void)testThatAddingConnectionByAttributeNameRespectsTransformationBlock
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
RKEntityMapping *humanEntityMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
[humanEntityMapping setSourceToDestinationKeyTransformationBlock:^NSString *(RKObjectMapping *mapping, NSString *sourceKey) {
|
||||
return @"age";
|
||||
}];
|
||||
[humanEntityMapping addConnectionForRelationship:@"favoriteCat" connectedBy:@"favoriteCatID"];
|
||||
RKConnectionDescription *connection = [humanEntityMapping connectionForRelationship:@"favoriteCat"];
|
||||
NSDictionary *expectedAttributes = @{ @"favoriteCatID": @"age" };
|
||||
expect(connection.attributes).to.equal(expectedAttributes);
|
||||
}
|
||||
|
||||
- (void)testAddingConnectionByArrayOfAttributeNames
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
RKEntityMapping *humanEntityMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
[humanEntityMapping addConnectionForRelationship:@"cats" connectedBy:@[ @"railsID", @"name" ]];
|
||||
RKConnectionDescription *connection = [humanEntityMapping connectionForRelationship:@"cats"];
|
||||
NSDictionary *expectedAttributes = @{ @"railsID": @"railsID", @"name": @"name" };
|
||||
expect(connection.attributes).to.equal(expectedAttributes);
|
||||
}
|
||||
|
||||
- (void)testAddingConnectionByArrayOfAttributeNamesRespectsTransformationBlock
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
RKEntityMapping *humanEntityMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
[humanEntityMapping setSourceToDestinationKeyTransformationBlock:^NSString *(RKObjectMapping *mapping, NSString *sourceKey) {
|
||||
if ([sourceKey isEqualToString:@"railsID"]) return @"age";
|
||||
else if ([sourceKey isEqualToString:@"name"]) return @"color";
|
||||
else return sourceKey;
|
||||
}];
|
||||
[humanEntityMapping addConnectionForRelationship:@"cats" connectedBy:@[ @"railsID", @"name" ]];
|
||||
RKConnectionDescription *connection = [humanEntityMapping connectionForRelationship:@"cats"];
|
||||
NSDictionary *expectedAttributes = @{ @"railsID": @"age", @"name": @"color" };
|
||||
expect(connection.attributes).to.equal(expectedAttributes);
|
||||
}
|
||||
|
||||
- (void)testAddingConnectionByDictionaryOfAttributes
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
RKEntityMapping *humanEntityMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
[humanEntityMapping addConnectionForRelationship:@"cats" connectedBy:@{ @"railsID": @"railsID", @"name": @"name" }];
|
||||
RKConnectionDescription *connection = [humanEntityMapping connectionForRelationship:@"cats"];
|
||||
NSDictionary *expectedAttributes = @{ @"railsID": @"railsID", @"name": @"name" };
|
||||
expect(connection.attributes).to.equal(expectedAttributes);
|
||||
}
|
||||
|
||||
- (void)testSettingEntityIdentifierForRelationship
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
RKEntityMapping *humanEntityMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
[humanEntityMapping setEntityIdentifier:[RKEntityIdentifier identifierWithEntityName:@"Cat" attributes:@[ @"name" ] inManagedObjectStore:managedObjectStore] forRelationship:@"cats"];
|
||||
RKEntityIdentifier *entityIdentifier = [humanEntityMapping entityIdentifierForRelationship:@"cats"];
|
||||
expect(entityIdentifier).notTo.beNil();
|
||||
expect([entityIdentifier.attributes valueForKey:@"name"]).to.equal(@[ @"name" ]);
|
||||
}
|
||||
|
||||
- (void)testSettingEntityIdentifierForInvalidRelationshipRaisesError
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
RKEntityMapping *humanEntityMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
NSException *caughtException = nil;
|
||||
@try {
|
||||
[humanEntityMapping setEntityIdentifier:[RKEntityIdentifier identifierWithEntityName:@"Cat" attributes:@[ @"name" ] inManagedObjectStore:managedObjectStore] forRelationship:@"invalid"];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
caughtException = exception;
|
||||
}
|
||||
@finally {
|
||||
expect(caughtException).notTo.beNil();
|
||||
expect([caughtException reason]).to.equal(@"Cannot set entity identififer for relationship 'invalid': no relationship found for that name.");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testSettingEntityIdentifierWithEntityMismatchRaisesError
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
RKEntityMapping *humanEntityMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
NSException *caughtException = nil;
|
||||
@try {
|
||||
[humanEntityMapping setEntityIdentifier:[RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"name" ] inManagedObjectStore:managedObjectStore] forRelationship:@"cats"];
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
caughtException = exception;
|
||||
}
|
||||
@finally {
|
||||
NSLog(@"In finally the exception is: %@", caughtException);
|
||||
expect(caughtException).notTo.beNil();
|
||||
expect([caughtException reason]).to.equal(@"Cannot set entity identifier for relationship 'cats': the given relationship identifier is for the 'Human' entity, but the 'Cat' entity was expected.");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testEntityIdentifierInferenceOnInit
|
||||
{
|
||||
[RKEntityMapping setEntityIdentifierInferenceEnabled:YES];
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Parent" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
RKEntityMapping *entityMapping = [[RKEntityMapping alloc] initWithEntity:entity];
|
||||
expect(entityMapping.entityIdentifier).notTo.beNil();
|
||||
assertThat([entityMapping.entityIdentifier.attributes valueForKey:@"name"], equalTo(@[ @"parentID" ]));
|
||||
}
|
||||
|
||||
- (void)testInitWithIdentifierInferenceEnabledInfersIdentifiersForRelationships
|
||||
{
|
||||
[RKEntityMapping setEntityIdentifierInferenceEnabled:YES];
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Parent" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
RKEntityMapping *entityMapping = [[RKEntityMapping alloc] initWithEntity:entity];
|
||||
|
||||
RKEntityIdentifier *childrenIdentifier = [entityMapping entityIdentifierForRelationship:@"children"];
|
||||
expect(childrenIdentifier).notTo.beNil();
|
||||
assertThat([childrenIdentifier.attributes valueForKey:@"name"], equalTo(@[ @"childID" ]));
|
||||
}
|
||||
|
||||
- (void)testInitWithIdentifierInferenceDisabled
|
||||
{
|
||||
[RKEntityMapping setEntityIdentifierInferenceEnabled:NO];
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Parent" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
RKEntityMapping *entityMapping = [[RKEntityMapping alloc] initWithEntity:entity];
|
||||
expect(entityMapping.entityIdentifier).to.beNil();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
RKFetchRequestManagedObjectCache *cache = [RKFetchRequestManagedObjectCache new];
|
||||
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Cat" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Cat" inManagedObjectStore:managedObjectStore];
|
||||
[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
mapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Cat" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
|
||||
RKCat *reginald = [NSEntityDescription insertNewObjectForEntityForName:@"Cat" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
reginald.name = @"Reginald";
|
||||
@@ -44,17 +44,17 @@
|
||||
RKFetchRequestManagedObjectCache *cache = [RKFetchRequestManagedObjectCache new];
|
||||
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Event" inManagedObjectStore:managedObjectStore];
|
||||
[mapping setEntityIdentifierWithAttributes:@"eventID"];
|
||||
mapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Event" attributes:@[ @"eventID" ] inManagedObjectStore:managedObjectStore];
|
||||
|
||||
RKEvent *birthday = [NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
birthday.eventID = @"e-1234-a8-b12";
|
||||
[managedObjectStore.persistentStoreManagedObjectContext save:nil];
|
||||
|
||||
NSManagedObject *cachedObject = [cache findInstanceOfEntity:entity
|
||||
withPrimaryKeyAttribute:mapping.primaryKeyAttribute
|
||||
value:@"e-1234-a8-b12"
|
||||
inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
expect(cachedObject).to.equal(birthday);
|
||||
|
||||
NSArray *managedObjects = [cache managedObjectsWithEntity:entity
|
||||
attributeValues:@{ @"eventID": @"e-1234-a8-b12" }
|
||||
inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
NSArray *birthdays = @[ birthday ];
|
||||
expect(managedObjects).to.equal(birthdays);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
inManagedObjectStore:managedObjectStore];
|
||||
[humanMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"id" toKeyPath:@"railsID"]];
|
||||
[humanMapping addAttributeMappingsFromArray:@[@"name"]];
|
||||
human[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
humanmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
humanMapping.rootKeyPath = @"human";
|
||||
|
||||
// Create 3 objects, we will expect 2 after the load
|
||||
@@ -167,7 +167,7 @@
|
||||
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
[humanMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"id" toKeyPath:@"railsID"]];
|
||||
[humanMapping addAttributeMappingsFromArray:@[@"name"]];
|
||||
human[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
humanmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
humanMapping.rootKeyPath = @"human";
|
||||
|
||||
NSError *error;
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
//
|
||||
|
||||
#import "RKTestEnvironment.h"
|
||||
#import "NSEntityDescription+RKAdditions.h"
|
||||
#import "RKEntityCache.h"
|
||||
#import "RKEntityByAttributeCache.h"
|
||||
#import "RKHuman.h"
|
||||
@@ -48,8 +47,7 @@
|
||||
RKManagedObjectMappingOperationDataSource *dataSource = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext
|
||||
cache:managedObjectStore.managedObjectCache];
|
||||
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
mapping.entityIdentifier = [RKEntityIdentifier entityIdentifierWithEntityName:@" attributes:<#(NSArray *)#> inManagedObjectStore:<#(RKManagedObjectStore *)#>]
|
||||
[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
mapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
|
||||
NSDictionary *data = [NSDictionary dictionary];
|
||||
id object = [dataSource mappingOperation:nil targetObjectForRepresentation:data withMapping:mapping];
|
||||
@@ -76,7 +74,7 @@
|
||||
RKManagedObjectMappingOperationDataSource *dataSource = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext
|
||||
cache:managedObjectStore.managedObjectCache];
|
||||
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
mapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"id" toKeyPath:@"railsID"]];
|
||||
|
||||
NSDictionary *data = [NSDictionary dictionaryWithObject:[NSNull null] forKey:@"id"];
|
||||
@@ -92,7 +90,7 @@
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
managedObjectStore.managedObjectCache = [RKFetchRequestManagedObjectCache new];
|
||||
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
mapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"id" toKeyPath:@"railsID"]];
|
||||
|
||||
RKHuman *human = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
@@ -102,14 +100,14 @@
|
||||
NSError *error = nil;
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Human"];
|
||||
NSUInteger count = [managedObjectStore.persistentStoreManagedObjectContext countForFetchRequest:fetchRequest error:&error];
|
||||
assertThat([NSNumber numberWithInteger:count], is(greaterThan([NSNumber numberWithInteger:0])));
|
||||
expect(count).to.beGreaterThan(0);
|
||||
|
||||
RKManagedObjectMappingOperationDataSource *dataSource = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext
|
||||
cache:managedObjectStore.managedObjectCache];
|
||||
NSDictionary *data = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:123] forKey:@"id"];
|
||||
id object = [dataSource mappingOperation:nil targetObjectForRepresentation:data withMapping:mapping];
|
||||
assertThat(object, isNot(nilValue()));
|
||||
assertThat(object, is(equalTo(human)));
|
||||
expect(object).notTo.beNil();
|
||||
expect(object).to.equal(human);
|
||||
}
|
||||
|
||||
- (void)testShouldFindExistingManagedObjectsByPrimaryKeyPathWithFetchedResultsCache
|
||||
@@ -117,7 +115,7 @@
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
managedObjectStore.managedObjectCache = [RKFetchRequestManagedObjectCache new];
|
||||
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
mapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"monkey.id" toKeyPath:@"railsID"]];
|
||||
|
||||
RKHuman *human = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
@@ -127,7 +125,7 @@
|
||||
NSError *error = nil;
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Human"];
|
||||
NSUInteger count = [managedObjectStore.persistentStoreManagedObjectContext countForFetchRequest:fetchRequest error:&error];
|
||||
assertThat([NSNumber numberWithInteger:count], is(greaterThan([NSNumber numberWithInteger:0])));
|
||||
expect(count).to.beGreaterThan(0);
|
||||
|
||||
NSDictionary *data = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:123] forKey:@"id"];
|
||||
NSDictionary *nestedDictionary = [NSDictionary dictionaryWithObject:data forKey:@"monkey"];
|
||||
@@ -135,8 +133,35 @@
|
||||
RKManagedObjectMappingOperationDataSource *dataSource = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext
|
||||
cache:managedObjectStore.managedObjectCache];
|
||||
id object = [dataSource mappingOperation:nil targetObjectForRepresentation:nestedDictionary withMapping:mapping];
|
||||
assertThat(object, isNot(nilValue()));
|
||||
assertThat(object, is(equalTo(human)));
|
||||
expect(object).notTo.beNil();
|
||||
expect(object).to.equal(human);
|
||||
}
|
||||
|
||||
- (void)testUsingDateAsIdentifierAttributeWithFetchRequestCache
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
managedObjectStore.managedObjectCache = [RKFetchRequestManagedObjectCache new];
|
||||
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
mapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"createdAt" ] inManagedObjectStore:managedObjectStore];
|
||||
[mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"monkey.created_at" toKeyPath:@"createdAt"]];
|
||||
|
||||
NSString *createdAtString = @"2012-03-22T11:05:42Z";
|
||||
NSDate *createdAtDate = RKDateFromString(createdAtString);
|
||||
RKHuman *human = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
human.createdAt = createdAtDate;
|
||||
[managedObjectStore.persistentStoreManagedObjectContext save:nil];
|
||||
|
||||
NSError *error = nil;
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Human"];
|
||||
NSUInteger count = [managedObjectStore.persistentStoreManagedObjectContext countForFetchRequest:fetchRequest error:&error];
|
||||
expect(count).to.beGreaterThan(0);
|
||||
|
||||
NSDictionary *representation = @{ @"monkey": @{ @"created_at": createdAtString } };
|
||||
RKManagedObjectMappingOperationDataSource *dataSource = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext
|
||||
cache:managedObjectStore.managedObjectCache];
|
||||
id object = [dataSource mappingOperation:nil targetObjectForRepresentation:representation withMapping:mapping];
|
||||
expect(object).notTo.beNil();
|
||||
expect(object).to.equal(human);
|
||||
}
|
||||
|
||||
#pragma mark - In Memory Cache
|
||||
@@ -146,7 +171,7 @@
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
mapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"id" toKeyPath:@"railsID"]];
|
||||
|
||||
RKHuman *human = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
@@ -157,15 +182,15 @@
|
||||
NSError *error = nil;
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Human"];
|
||||
NSUInteger count = [managedObjectStore.persistentStoreManagedObjectContext countForFetchRequest:fetchRequest error:&error];
|
||||
assertThat([NSNumber numberWithInteger:count], is(greaterThan([NSNumber numberWithInteger:0])));
|
||||
expect(count).to.beGreaterThan(0);
|
||||
|
||||
NSDictionary *data = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:123] forKey:@"id"];
|
||||
RKManagedObjectMappingOperationDataSource *dataSource = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext
|
||||
cache:managedObjectStore.managedObjectCache];
|
||||
NSManagedObject *object = [dataSource mappingOperation:nil targetObjectForRepresentation:data withMapping:mapping];
|
||||
assertThat([object managedObjectContext], is(equalTo(managedObjectStore.persistentStoreManagedObjectContext)));
|
||||
assertThat(object, isNot(nilValue()));
|
||||
assertThat(object, is(equalTo(human)));
|
||||
expect([object managedObjectContext]).to.equal(managedObjectStore.persistentStoreManagedObjectContext);
|
||||
expect(object).notTo.beNil();
|
||||
expect(object).to.equal(human);
|
||||
}
|
||||
|
||||
- (void)testShouldFindExistingManagedObjectsByPrimaryKeyPathWithInMemoryCache
|
||||
@@ -173,7 +198,7 @@
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
mapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"monkey.id" toKeyPath:@"railsID"]];
|
||||
|
||||
RKHuman *human = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
@@ -196,68 +221,31 @@
|
||||
assertThat(object, is(equalTo(human)));
|
||||
}
|
||||
|
||||
- (void)testMappingWithFetchRequestCacheWherePrimaryKeyAttributeOfMappingDisagreesWithEntity
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
managedObjectStore.managedObjectCache = [RKFetchRequestManagedObjectCache new];
|
||||
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
mapping.primaryKeyAttribute = @"name";
|
||||
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
entity.primaryKeyAttributeName = @"railsID";
|
||||
[mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"monkey.name" toKeyPath:@"name"]];
|
||||
|
||||
RKHuman *human = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
human.name = @"Testing";
|
||||
[managedObjectStore.persistentStoreManagedObjectContext save:nil];
|
||||
|
||||
// Check the count
|
||||
NSError *error = nil;
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Human"];
|
||||
NSUInteger count = [managedObjectStore.persistentStoreManagedObjectContext countForFetchRequest:fetchRequest error:&error];
|
||||
assertThat([NSNumber numberWithInteger:count], is(greaterThan([NSNumber numberWithInteger:0])));
|
||||
|
||||
NSDictionary *data = [NSDictionary dictionaryWithObject:@"Testing" forKey:@"name"];
|
||||
NSDictionary *nestedDictionary = [NSDictionary dictionaryWithObject:data forKey:@"monkey"];
|
||||
RKManagedObjectMappingOperationDataSource *dataSource = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext
|
||||
cache:managedObjectStore.managedObjectCache];
|
||||
id object = [dataSource mappingOperation:nil targetObjectForRepresentation:nestedDictionary withMapping:mapping];
|
||||
assertThat(object, isNot(nilValue()));
|
||||
assertThat(object, is(equalTo(human)));
|
||||
|
||||
id cachedObject = [managedObjectStore.managedObjectCache findInstanceOfEntity:entity withPrimaryKeyAttribute:@"name" value:@"Testing" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
assertThat(cachedObject, is(equalTo(human)));
|
||||
}
|
||||
|
||||
- (void)testMappingWithInMemoryCacheWherePrimaryKeyAttributeOfMappingDisagreesWithEntity
|
||||
- (void)testUsingDateAsIdentifierAttributeWithInMemoryCache
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
RKEntityMapping *mapping = [[RKEntityMapping alloc] initWithEntity:entity];
|
||||
mapping.primaryKeyAttribute = @"name";
|
||||
entity.primaryKeyAttributeName = @"railsID";
|
||||
[mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"monkey.name" toKeyPath:@"name"]];
|
||||
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
mapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"createdAt" ] inManagedObjectStore:managedObjectStore];
|
||||
[mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"monkey.created_at" toKeyPath:@"createdAt"]];
|
||||
|
||||
NSString *createdAtString = @"2012-03-22T11:05:42Z";
|
||||
NSDate *createdAtDate = RKDateFromString(createdAtString);
|
||||
RKHuman *human = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
human.name = @"Testing";
|
||||
human.createdAt = createdAtDate;
|
||||
[managedObjectStore.persistentStoreManagedObjectContext save:nil];
|
||||
|
||||
// Check the count
|
||||
|
||||
NSError *error = nil;
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Human"];
|
||||
NSUInteger count = [managedObjectStore.persistentStoreManagedObjectContext countForFetchRequest:fetchRequest error:&error];
|
||||
assertThatInteger(count, is(greaterThan([NSNumber numberWithInteger:0])));
|
||||
expect(count).to.beGreaterThan(0);
|
||||
|
||||
NSDictionary *data = [NSDictionary dictionaryWithObject:@"Testing" forKey:@"name"];
|
||||
NSDictionary *nestedDictionary = [NSDictionary dictionaryWithObject:data forKey:@"monkey"];
|
||||
NSDictionary *representation = @{ @"monkey": @{ @"created_at": createdAtString } };
|
||||
RKManagedObjectMappingOperationDataSource *dataSource = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext
|
||||
cache:managedObjectStore.managedObjectCache];
|
||||
id object = [dataSource mappingOperation:nil targetObjectForRepresentation:nestedDictionary withMapping:mapping];
|
||||
assertThat(object, isNot(nilValue()));
|
||||
assertThat(object, is(equalTo(human)));
|
||||
|
||||
id cachedObject = [managedObjectStore.managedObjectCache findInstanceOfEntity:entity withPrimaryKeyAttribute:@"name" value:@"Testing" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
assertThat(cachedObject, is(equalTo(human)));
|
||||
id object = [dataSource mappingOperation:nil targetObjectForRepresentation:representation withMapping:mapping];
|
||||
expect(object).notTo.beNil();
|
||||
expect(object).to.equal(human);
|
||||
}
|
||||
|
||||
- (void)testThatCreationOfNewObjectWithIncorrectTypeValueForPrimaryKeyAddsToCache
|
||||
@@ -266,8 +254,7 @@
|
||||
managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
RKEntityMapping *mapping = [[RKEntityMapping alloc] initWithEntity:entity];
|
||||
[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
entity.primaryKeyAttributeName = @"railsID";
|
||||
mapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"monkey.name" toKeyPath:@"name"]];
|
||||
[mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"monkey.railsID" toKeyPath:@"railsID"]];
|
||||
|
||||
@@ -298,8 +285,8 @@
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
RKEntityMapping *mapping = [[RKEntityMapping alloc] initWithEntity:entity];
|
||||
RKConnectionMapping *connectionMapping = [[RKConnectionMapping alloc] initWithRelationship:entity.relationshipsByName[@"favoriteCat"] sourceKeyPath:@"test" destinationKeyPath:@"test" matcher:nil];
|
||||
[mapping addConnectionMapping:connectionMapping];
|
||||
RKConnectionDescription *connection = [[RKConnectionDescription alloc] initWithRelationship:entity.relationshipsByName[@"favoriteCat"] attributes:@{ @"railsID": @"railsID" }];
|
||||
[mapping addConnection:connection];
|
||||
|
||||
RKManagedObjectMappingOperationDataSource *dataSource = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext
|
||||
cache:nil];
|
||||
@@ -312,4 +299,183 @@
|
||||
expect([error localizedDescription]).to.equal(@"Cannot map an entity mapping that contains connection mappings with a data source whose managed object cache is nil.");
|
||||
}
|
||||
|
||||
#pragma mark - Rearrange Me
|
||||
|
||||
- (void)testCompoundEntityIdentifierWithFetchRequestCache
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
managedObjectStore.managedObjectCache = [RKFetchRequestManagedObjectCache new];
|
||||
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
mapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID", @"name", @"createdAt" ] inManagedObjectStore:managedObjectStore];
|
||||
[mapping addAttributeMappingsFromDictionary:@{ @"monkey.id": @"railsID", @"monkey.name": @"name", @"monkey.created_at": @"createdAt" }];
|
||||
|
||||
NSString *createdAtString = @"2012-03-22T11:05:42Z";
|
||||
NSDate *createdAtDate = RKDateFromString(createdAtString);
|
||||
RKHuman *human = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
human.railsID = @(12345);
|
||||
human.createdAt = createdAtDate;
|
||||
human.name = @"Reginald";
|
||||
[managedObjectStore.persistentStoreManagedObjectContext save:nil];
|
||||
|
||||
// Check the count
|
||||
NSError *error = nil;
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Human"];
|
||||
NSUInteger count = [managedObjectStore.persistentStoreManagedObjectContext countForFetchRequest:fetchRequest error:&error];
|
||||
assertThat([NSNumber numberWithInteger:count], is(greaterThan([NSNumber numberWithInteger:0])));
|
||||
|
||||
NSDictionary *representation = @{ @"monkey": @{ @"id": @"12345", @"name": @"Reginald", @"created_at": createdAtString } };
|
||||
|
||||
RKManagedObjectMappingOperationDataSource *dataSource = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext
|
||||
cache:managedObjectStore.managedObjectCache];
|
||||
id object = [dataSource mappingOperation:nil targetObjectForRepresentation:representation withMapping:mapping];
|
||||
assertThat(object, isNot(nilValue()));
|
||||
assertThat(object, is(equalTo(human)));
|
||||
}
|
||||
|
||||
- (void)testCompoundEntityIdentifierWithInMemoryCache
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
mapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID", @"name", @"createdAt" ] inManagedObjectStore:managedObjectStore];
|
||||
[mapping addAttributeMappingsFromDictionary:@{ @"monkey.id": @"railsID", @"monkey.name": @"name", @"monkey.created_at": @"createdAt" }];
|
||||
|
||||
NSString *createdAtString = @"2012-03-22T11:05:42Z";
|
||||
NSDate *createdAtDate = RKDateFromString(createdAtString);
|
||||
RKHuman *human = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
human.railsID = @(12345);
|
||||
human.createdAt = createdAtDate;
|
||||
human.name = @"Reginald";
|
||||
[managedObjectStore.persistentStoreManagedObjectContext save:nil];
|
||||
|
||||
// Check the count
|
||||
NSError *error = nil;
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Human"];
|
||||
NSUInteger count = [managedObjectStore.persistentStoreManagedObjectContext countForFetchRequest:fetchRequest error:&error];
|
||||
assertThat([NSNumber numberWithInteger:count], is(greaterThan([NSNumber numberWithInteger:0])));
|
||||
|
||||
NSDictionary *representation = @{ @"monkey": @{ @"id": @"12345", @"name": @"Reginald", @"created_at": createdAtString } };
|
||||
|
||||
RKManagedObjectMappingOperationDataSource *dataSource = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext
|
||||
cache:managedObjectStore.managedObjectCache];
|
||||
id object = [dataSource mappingOperation:nil targetObjectForRepresentation:representation withMapping:mapping];
|
||||
assertThat(object, isNot(nilValue()));
|
||||
assertThat(object, is(equalTo(human)));
|
||||
}
|
||||
|
||||
- (void)testRetrievalOfTargetObjectInWhichIdentifierAttributeIsDynamicNestingKey
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
managedObjectStore.managedObjectCache = [RKFetchRequestManagedObjectCache new];
|
||||
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
mapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"name" ] inManagedObjectStore:managedObjectStore];
|
||||
[mapping addAttributeMappingFromKeyOfRepresentationToAttribute:@"name"];
|
||||
[mapping addAttributeMappingsFromDictionary:@{ @"(name).id": @"railsID" }];
|
||||
|
||||
RKHuman *human = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
human.name = @"Blake";
|
||||
human.railsID = @(12345);
|
||||
[managedObjectStore.persistentStoreManagedObjectContext save:nil];
|
||||
|
||||
NSError *error = nil;
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Human"];
|
||||
NSUInteger count = [managedObjectStore.persistentStoreManagedObjectContext countForFetchRequest:fetchRequest error:&error];
|
||||
expect(count).to.beGreaterThan(0);
|
||||
|
||||
RKManagedObjectMappingOperationDataSource *dataSource = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext
|
||||
cache:managedObjectStore.managedObjectCache];
|
||||
NSDictionary *representation = @{ @"Blake": @{ @"id": @"12345" } };
|
||||
id object = [dataSource mappingOperation:nil targetObjectForRepresentation:representation withMapping:mapping];
|
||||
expect(object).notTo.beNil();
|
||||
expect(object).to.equal(human);
|
||||
}
|
||||
|
||||
- (void)testRetrievalOfTargetObjectInWhichIdentifierAttributeIsCompoundAndOneAttributeIsTheDynamicNestingKey
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
managedObjectStore.managedObjectCache = [RKFetchRequestManagedObjectCache new];
|
||||
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
mapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"name", @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[mapping addAttributeMappingFromKeyOfRepresentationToAttribute:@"name"];
|
||||
[mapping addAttributeMappingsFromDictionary:@{ @"(name).id": @"railsID" }];
|
||||
|
||||
RKHuman *human = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
human.name = @"Blake";
|
||||
human.railsID = @(12345);
|
||||
[managedObjectStore.persistentStoreManagedObjectContext save:nil];
|
||||
|
||||
NSError *error = nil;
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Human"];
|
||||
NSUInteger count = [managedObjectStore.persistentStoreManagedObjectContext countForFetchRequest:fetchRequest error:&error];
|
||||
expect(count).to.beGreaterThan(0);
|
||||
|
||||
RKManagedObjectMappingOperationDataSource *dataSource = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext
|
||||
cache:managedObjectStore.managedObjectCache];
|
||||
NSDictionary *representation = @{ @"Blake": @{ @"id": @"12345" } };
|
||||
id object = [dataSource mappingOperation:nil targetObjectForRepresentation:representation withMapping:mapping];
|
||||
expect(object).notTo.beNil();
|
||||
expect(object).to.equal(human);
|
||||
}
|
||||
|
||||
- (void)testRetrievalOfTargetObjectInWhichIdentifierAttributeIsCompoundAndOneAttributeIsTheDynamicNestingKeyAndItIsNotTheFirstIdentifierAttribute
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
managedObjectStore.managedObjectCache = [RKFetchRequestManagedObjectCache new];
|
||||
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
mapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID", @"name" ] inManagedObjectStore:managedObjectStore];
|
||||
[mapping addAttributeMappingFromKeyOfRepresentationToAttribute:@"name"];
|
||||
[mapping addAttributeMappingsFromDictionary:@{ @"(name).id": @"railsID" }];
|
||||
|
||||
RKHuman *human = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
human.name = @"Blake";
|
||||
human.railsID = @(12345);
|
||||
[managedObjectStore.persistentStoreManagedObjectContext save:nil];
|
||||
|
||||
NSError *error = nil;
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Human"];
|
||||
NSUInteger count = [managedObjectStore.persistentStoreManagedObjectContext countForFetchRequest:fetchRequest error:&error];
|
||||
expect(count).to.beGreaterThan(0);
|
||||
|
||||
RKManagedObjectMappingOperationDataSource *dataSource = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext
|
||||
cache:managedObjectStore.managedObjectCache];
|
||||
NSDictionary *representation = @{ @"Blake": @{ @"id": @"12345" } };
|
||||
id object = [dataSource mappingOperation:nil targetObjectForRepresentation:representation withMapping:mapping];
|
||||
expect(object).notTo.beNil();
|
||||
expect(object).to.equal(human);
|
||||
}
|
||||
|
||||
- (void)testEntityIdentifierWithPredicate
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
managedObjectStore.managedObjectCache = [RKFetchRequestManagedObjectCache new];
|
||||
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
mapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
mapping.entityIdentifier.predicate = [NSPredicate predicateWithFormat:@"age < 30"];
|
||||
[mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"id" toKeyPath:@"railsID"]];
|
||||
|
||||
// Create two humans matching the identifier, but differ in matching the
|
||||
RKHuman *human1 = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
human1.name = @"Colin";
|
||||
human1.railsID = [NSNumber numberWithInt:123];
|
||||
human1.age = @28;
|
||||
|
||||
RKHuman *human2 = [NSEntityDescription insertNewObjectForEntityForName:@"Human" inManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
|
||||
human2.name = @"Blake";
|
||||
human2.railsID = [NSNumber numberWithInt:123];
|
||||
human2.age = @30;
|
||||
[managedObjectStore.persistentStoreManagedObjectContext save:nil];
|
||||
|
||||
NSError *error = nil;
|
||||
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Human"];
|
||||
NSUInteger count = [managedObjectStore.persistentStoreManagedObjectContext countForFetchRequest:fetchRequest error:&error];
|
||||
expect(count).to.beGreaterThan(0);
|
||||
|
||||
RKManagedObjectMappingOperationDataSource *dataSource = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext
|
||||
cache:managedObjectStore.managedObjectCache];
|
||||
NSDictionary *data = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:123] forKey:@"id"];
|
||||
id object = [dataSource mappingOperation:nil targetObjectForRepresentation:data withMapping:mapping];
|
||||
expect(object).notTo.beNil();
|
||||
expect(object).to.equal(human1);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
NSDictionary *sourceObject = @{ @"name" : @"Blake Watters" };
|
||||
[managedObjectContext performBlockAndWait:^{
|
||||
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
human[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
humanmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[humanMapping addAttributeMappingsFromArray:@[@"name", @"favoriteCatID"]];
|
||||
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Human" inManagedObjectContext:managedObjectContext];
|
||||
RKHuman *human = [[RKHuman alloc] initWithEntity:entity insertIntoManagedObjectContext:managedObjectContext];
|
||||
@@ -76,11 +76,11 @@
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
|
||||
RKEntityMapping *catMapping = [RKEntityMapping mappingForEntityForName:@"Cat" inManagedObjectStore:managedObjectStore];
|
||||
cat[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
catmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[catMapping addAttributeMappingsFromArray:@[@"name"]];
|
||||
|
||||
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
human[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
humanmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[humanMapping addAttributeMappingsFromArray:@[@"name", @"favoriteCatID"]];
|
||||
[humanMapping connectRelationship:@"favoriteCat" fromKeyPath:@"favoriteCatID" toKeyPath:@"railsID" withMapping:catMapping];
|
||||
|
||||
@@ -110,11 +110,11 @@
|
||||
NSManagedObjectContext *managedObjectContext = managedObjectStore.persistentStoreManagedObjectContextContext;
|
||||
|
||||
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
human[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
humanmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[humanMapping addAttributeMappingsFromArray:@[@"name", @"favoriteCatID"]];
|
||||
|
||||
RKEntityMapping *catMapping = [RKEntityMapping mappingForEntityForName:@"Cat" inManagedObjectStore:managedObjectStore];
|
||||
cat[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
catmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[catMapping addAttributeMappingsFromArray:@[@"name", @"railsID"]];
|
||||
[catMapping connectRelationship:@"favoriteOfHumans" fromKeyPath:@"railsID" toKeyPath:@"favoriteCatID" withMapping:humanMapping];
|
||||
|
||||
@@ -158,11 +158,11 @@
|
||||
RKManagedObjectStore* managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
|
||||
RKEntityMapping *catMapping = [RKEntityMapping mappingForEntityForName:@"Cat" inManagedObjectStore:managedObjectStore];
|
||||
cat[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
catmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[catMapping addAttributeMappingsFromArray:@[@"name"]];
|
||||
|
||||
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
human[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
humanmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[humanMapping addAttributeMappingsFromArray:@[@"name", @"favoriteCatID"]];
|
||||
[humanMapping connectRelationship:@"favoriteCat" fromKeyPath:@"favoriteCatID" toKeyPath:@"railsID" withMapping:catMapping];
|
||||
|
||||
@@ -191,11 +191,11 @@
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
|
||||
RKEntityMapping *catMapping = [RKEntityMapping mappingForEntityForName:@"Cat" inManagedObjectStore:managedObjectStore];
|
||||
cat[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
catmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[catMapping addAttributeMappingsFromArray:@[@"name"]];
|
||||
|
||||
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
human[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
humanmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[humanMapping addAttributeMappingsFromArray:@[@"name", @"favoriteCatID"]];
|
||||
[humanMapping connectRelationship:@"favoriteCat" fromKeyPath:@"favoriteCatID" toKeyPath:@"railsID" withMapping:catMapping];
|
||||
|
||||
@@ -224,11 +224,11 @@
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
|
||||
RKEntityMapping *catMapping = [RKEntityMapping mappingForEntityForName:@"Cat" inManagedObjectStore:managedObjectStore];
|
||||
cat[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
catmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[catMapping addAttributeMappingsFromArray:@[@"name"]];
|
||||
|
||||
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
human[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
humanmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[humanMapping addAttributeMappingsFromArray:@[@"name", @"catIDs"]];
|
||||
[humanMapping connectRelationship:@"cats" fromKeyPath:@"catIDs" toKeyPath:@"railsID" withMapping:catMapping];
|
||||
|
||||
@@ -265,11 +265,11 @@
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
|
||||
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
human[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
humanmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[humanMapping addAttributeMappingsFromArray:@[@"name", @"railsID"]];
|
||||
|
||||
RKEntityMapping *catMapping = [RKEntityMapping mappingForEntityForName:@"Cat" inManagedObjectStore:managedObjectStore];
|
||||
cat[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
catmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[catMapping addAttributeMappingsFromArray:@[@"name", @"humanId"]];
|
||||
[catMapping connectRelationship:@"human" fromKeyPath:@"humanId" toKeyPath:@"railsID" withMapping:humanMapping];
|
||||
|
||||
@@ -297,11 +297,11 @@
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
RKEntityMapping *catMapping = [RKEntityMapping mappingForEntityForName:@"Cat" inManagedObjectStore:managedObjectStore];
|
||||
cat[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
catmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[catMapping addAttributeMappingsFromArray:@[@"name"]];
|
||||
|
||||
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
human[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
humanmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[humanMapping addAttributeMappingsFromArray:@[@"name", @"favoriteCatID"]];
|
||||
[humanMapping hasMany:@"cats" withMapping:catMapping];
|
||||
|
||||
@@ -322,11 +322,11 @@
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
RKEntityMapping *catMapping = [RKEntityMapping mappingForEntityForName:@"Cat" inManagedObjectStore:managedObjectStore];
|
||||
cat[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
catmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[catMapping addAttributeMappingsFromArray:@[@"name"]];
|
||||
|
||||
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
human[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
humanmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[humanMapping addAttributeMappingsFromArray:@[@"name", @"favoriteCatID"]];
|
||||
[humanMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"cats" toKeyPath:@"catsInOrderByAge" withMapping:catMapping]];;
|
||||
|
||||
@@ -396,11 +396,11 @@
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
|
||||
RKEntityMapping *catMapping = [RKEntityMapping mappingForEntityForName:@"Cat" inManagedObjectStore:managedObjectStore];
|
||||
cat[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
catmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[catMapping addAttributeMappingsFromArray:@[@"name"]];
|
||||
|
||||
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
human[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
humanmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[humanMapping addAttributeMappingsFromArray:@[@"name", @"favoriteCatID"]];
|
||||
[humanMapping connectRelationship:@"favoriteCat" fromKeyPath:@"favoriteCatID" toKeyPath:@"railsID" withMapping:catMapping whenValueOfKeyPath:@"name" isEqualTo:@"Blake"];
|
||||
|
||||
@@ -429,11 +429,11 @@
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
|
||||
RKEntityMapping *catMapping = [RKEntityMapping mappingForEntityForName:@"Cat" inManagedObjectStore:managedObjectStore];
|
||||
cat[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
catmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[catMapping addAttributeMappingsFromArray:@[@"name"]];
|
||||
|
||||
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
human[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
humanmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[humanMapping addAttributeMappingsFromArray:@[@"name", @"favoriteCatID"]];
|
||||
[humanMapping connectRelationship:@"favoriteCat" fromKeyPath:@"favoriteCatID" toKeyPath:@"railsID" withMapping:catMapping whenValueOfKeyPath:@"name" isEqualTo:@"Jeff"];
|
||||
|
||||
@@ -460,11 +460,11 @@
|
||||
{
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
RKEntityMapping *childMapping = [RKEntityMapping mappingForEntityForName:@"Child" inManagedObjectStore:managedObjectStore];
|
||||
child[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
childmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[childMapping addAttributeMappingsFromArray:@[@"name"]];
|
||||
|
||||
RKEntityMapping *parentMapping = [RKEntityMapping mappingForEntityForName:@"Parent" inManagedObjectStore:managedObjectStore];
|
||||
parent[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
parentmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[parentMapping addAttributeMappingsFromArray:@[@"name", @"age"]];
|
||||
[parentMapping hasMany:@"children" withMapping:childMapping];
|
||||
|
||||
@@ -698,11 +698,11 @@
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
|
||||
RKEntityMapping* catMapping = [RKEntityMapping mappingForEntityForName:@"Cat" inManagedObjectStore:managedObjectStore];
|
||||
cat[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
catmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[catMapping addAttributeMappingsFromArray:@[@"name"]];
|
||||
|
||||
RKEntityMapping* humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
human[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
humanmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[humanMapping addAttributeMappingsFromArray:@[@"name", @"favoriteCatID"]];
|
||||
[humanMapping hasOne:@"favoriteCat" withMapping:catMapping];
|
||||
[humanMapping connectRelationship:@"favoriteCat" withObjectForPrimaryKeyAttribute:@"favoriteCatID"];
|
||||
@@ -731,11 +731,11 @@
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
|
||||
RKEntityMapping* catMapping = [RKEntityMapping mappingForEntityForName:@"Cat" inManagedObjectStore:managedObjectStore];
|
||||
cat[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
catmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[catMapping addAttributeMappingsFromArray:@[@"name"]];
|
||||
|
||||
RKEntityMapping* humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
human[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
humanmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[humanMapping addAttributeMappingsFromArray:@[@"name", @"favoriteCatID"]];
|
||||
[humanMapping hasOne:@"favoriteCat" withMapping:catMapping];
|
||||
[humanMapping connectRelationship:@"favoriteCat" withObjectForPrimaryKeyAttribute:@"favoriteCatID"];
|
||||
@@ -764,11 +764,11 @@
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
|
||||
RKEntityMapping* catMapping = [RKEntityMapping mappingForEntityForName:@"Cat" inManagedObjectStore:managedObjectStore];
|
||||
cat[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
catmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[catMapping addAttributeMappingsFromArray:@[@"name"]];
|
||||
|
||||
RKEntityMapping* humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
human[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
humanmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[humanMapping addAttributeMappingsFromArray:@[@"name", @"favoriteCatID"]];
|
||||
[humanMapping hasOne:@"favoriteCat" withMapping:catMapping];
|
||||
[humanMapping connectRelationship:@"favoriteCat" withObjectForPrimaryKeyAttribute:@"favoriteCatID"];
|
||||
@@ -797,11 +797,11 @@
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
|
||||
RKEntityMapping* catMapping = [RKEntityMapping mappingForEntityForName:@"Cat" inManagedObjectStore:managedObjectStore];
|
||||
cat[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
catmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[catMapping addAttributeMappingsFromArray:@[@"name"]];
|
||||
|
||||
RKEntityMapping* humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
human[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
humanmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[humanMapping addAttributeMappingsFromArray:@[@"name", @"favoriteCatID", @"catIDs"]];
|
||||
[humanMapping mapRelationship:@"cats" withMapping:catMapping];
|
||||
[humanMapping connectRelationship:@"cats" withObjectForPrimaryKeyAttribute:@"catIDs"];
|
||||
@@ -837,11 +837,11 @@
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
|
||||
RKEntityMapping* catMapping = [RKEntityMapping mappingForEntityForName:@"Cat" inManagedObjectStore:managedObjectStore];
|
||||
cat[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
catmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[catMapping addAttributeMappingsFromArray:@[@"name"]];
|
||||
|
||||
RKEntityMapping* humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
human[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
humanmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[humanMapping addAttributeMappingsFromArray:@[@"name", @"favoriteCatID"]];
|
||||
[humanMapping hasOne:@"favoriteCat" withMapping:catMapping];
|
||||
[humanMapping connectRelationship:@"favoriteCat" withObjectForPrimaryKeyAttribute:@"favoriteCatID" whenValueOfKeyPath:@"name" isEqualTo:@"Blake"];
|
||||
@@ -870,11 +870,11 @@
|
||||
RKManagedObjectStore *managedObjectStore = [RKTestFactory managedObjectStore];
|
||||
|
||||
RKEntityMapping* catMapping = [RKEntityMapping mappingForEntityForName:@"Cat" inManagedObjectStore:managedObjectStore];
|
||||
cat[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
catmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[catMapping addAttributeMappingsFromArray:@[@"name"]];
|
||||
|
||||
RKEntityMapping* humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
human[mapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
humanmapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
[humanMapping addAttributeMappingsFromArray:@[@"name", @"favoriteCatID"]];
|
||||
[humanMapping hasOne:@"favoriteCat" withMapping:catMapping];
|
||||
[humanMapping connectRelationship:@"favoriteCat" withObjectForPrimaryKeyAttribute:@"favoriteCatID" whenValueOfKeyPath:@"name" isEqualTo:@"Jeff"];
|
||||
|
||||
@@ -37,9 +37,10 @@
|
||||
RKCat *asia = [RKTestFactory insertManagedObjectForEntityForName:@"Cat" inManagedObjectContext:nil withProperties:nil];
|
||||
asia.railsID = @250;
|
||||
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:[RKTestFactory managedObjectStore]];
|
||||
RKConnectionMapping *connectionMapping = [mapping addConnectionMappingForRelationshipForName:@"favoriteCat" fromSourceKeyPath:@"favoriteCatID" toKeyPath:@"railsID" matcher:nil];
|
||||
[mapping addConnectionForRelationship:@"favoriteCat" connectedBy:@{ @"favoriteCatID": @"railsID" } ];
|
||||
RKConnectionDescription *connection = [mapping connectionForRelationship:@"favoriteCat"];
|
||||
RKFetchRequestManagedObjectCache *managedObjectCache = [RKFetchRequestManagedObjectCache new];
|
||||
RKRelationshipConnectionOperation *operation = [[RKRelationshipConnectionOperation alloc] initWithManagedObject:human connectionMapping:connectionMapping managedObjectCache:managedObjectCache];
|
||||
RKConnectionOperation *operation = [[RKConnectionOperation alloc] initWithManagedObject:human connection:connection managedObjectCache:managedObjectCache];
|
||||
[operation start];
|
||||
assertThat(human.favoriteCat, is(equalTo(asia)));
|
||||
}
|
||||
@@ -56,9 +57,10 @@
|
||||
roy.sex = @"male";
|
||||
|
||||
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:[RKTestFactory managedObjectStore]];
|
||||
RKConnectionMapping *connectionMapping = [mapping addConnectionMappingForRelationshipForName:@"cats" fromSourceKeyPath:@"sex" toKeyPath:@"sex" matcher:nil];
|
||||
[mapping addConnectionForRelationship:@"cats" connectedBy:@"sex"];
|
||||
RKFetchRequestManagedObjectCache *managedObjectCache = [RKFetchRequestManagedObjectCache new];
|
||||
RKRelationshipConnectionOperation *operation = [[RKRelationshipConnectionOperation alloc] initWithManagedObject:human connectionMapping:connectionMapping managedObjectCache:managedObjectCache];
|
||||
RKConnectionDescription *connection = [mapping connectionForRelationship:@"cats"];
|
||||
RKConnectionOperation *operation = [[RKConnectionOperation alloc] initWithManagedObject:human connection:connection managedObjectCache:managedObjectCache];
|
||||
[operation start];
|
||||
assertThat(human.cats, hasCountOf(2));
|
||||
assertThat(human.cats, hasItems(asia, lola, nil));
|
||||
@@ -80,9 +82,10 @@
|
||||
|
||||
// No cats with a sex of 'invalid'
|
||||
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:[RKTestFactory managedObjectStore]];
|
||||
RKConnectionMapping *connectionMapping = [mapping addConnectionMappingForRelationshipForName:@"cats" fromSourceKeyPath:@"sex" toKeyPath:@"sex" matcher:nil];
|
||||
[mapping addConnectionForRelationship:@"cats" connectedBy:@{ @"sex": @"sex" }];
|
||||
RKConnectionDescription *connection = [mapping connectionForRelationship:@"cats"];
|
||||
RKFetchRequestManagedObjectCache *managedObjectCache = [RKFetchRequestManagedObjectCache new];
|
||||
RKRelationshipConnectionOperation *operation = [[RKRelationshipConnectionOperation alloc] initWithManagedObject:human connectionMapping:connectionMapping managedObjectCache:managedObjectCache];
|
||||
RKConnectionOperation *operation = [[RKConnectionOperation alloc] initWithManagedObject:human connection:connection managedObjectCache:managedObjectCache];
|
||||
[operation start];
|
||||
assertThat(human.cats, is(empty()));
|
||||
}
|
||||
@@ -93,7 +96,7 @@
|
||||
{
|
||||
NSEntityDescription *entity = [[[RKTestFactory managedObjectStore] managedObjectModel] entitiesByName][@"Human"];
|
||||
NSRelationshipDescription *relationship = [entity relationshipsByName][@"landlord"];
|
||||
RKConnectionMapping *connectionMapping = [[RKConnectionMapping alloc] initWithRelationship:relationship sourceKeyPath:@"residence.owner" destinationKeyPath:nil matcher:nil];
|
||||
RKConnectionDescription *connection = [[RKConnectionDescription alloc] initWithRelationship:relationship keyPath:@"residence.owner"];
|
||||
|
||||
RKHuman *tenant = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:nil withProperties:nil];
|
||||
RKHuman *homeowner = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:nil withProperties:nil];
|
||||
@@ -102,7 +105,7 @@
|
||||
tenant.residence = house;
|
||||
|
||||
RKFetchRequestManagedObjectCache *managedObjectCache = [RKFetchRequestManagedObjectCache new];
|
||||
RKRelationshipConnectionOperation *operation = [[RKRelationshipConnectionOperation alloc] initWithManagedObject:tenant connectionMapping:connectionMapping managedObjectCache:managedObjectCache];
|
||||
RKConnectionOperation *operation = [[RKConnectionOperation alloc] initWithManagedObject:tenant connection:connection managedObjectCache:managedObjectCache];
|
||||
[operation start];
|
||||
|
||||
expect(tenant.landlord).to.equal(homeowner);
|
||||
@@ -112,7 +115,7 @@
|
||||
{
|
||||
NSEntityDescription *entity = [[[RKTestFactory managedObjectStore] managedObjectModel] entitiesByName][@"Human"];
|
||||
NSRelationshipDescription *relationship = [entity relationshipsByName][@"roommates"];
|
||||
RKConnectionMapping *connectionMapping = [[RKConnectionMapping alloc] initWithRelationship:relationship sourceKeyPath:@"house.residents" destinationKeyPath:nil matcher:nil];
|
||||
RKConnectionDescription *connection = [[RKConnectionDescription alloc] initWithRelationship:relationship keyPath:@"house.residents"];
|
||||
|
||||
RKHuman *human = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:nil withProperties:nil];
|
||||
RKHouse *house = [RKTestFactory insertManagedObjectForEntityForName:@"House" inManagedObjectContext:nil withProperties:nil];
|
||||
@@ -123,7 +126,7 @@
|
||||
house.residents = [NSSet setWithObjects:resident1, resident2, nil];
|
||||
|
||||
RKFetchRequestManagedObjectCache *managedObjectCache = [RKFetchRequestManagedObjectCache new];
|
||||
RKRelationshipConnectionOperation *operation = [[RKRelationshipConnectionOperation alloc] initWithManagedObject:human connectionMapping:connectionMapping managedObjectCache:managedObjectCache];
|
||||
RKConnectionOperation *operation = [[RKConnectionOperation alloc] initWithManagedObject:human connection:connection managedObjectCache:managedObjectCache];
|
||||
[operation start];
|
||||
|
||||
NSSet *expectedRoommates = [NSSet setWithObjects:resident1, resident2, nil];
|
||||
@@ -134,7 +137,7 @@
|
||||
{
|
||||
NSEntityDescription *entity = [[[RKTestFactory managedObjectStore] managedObjectModel] entitiesByName][@"Human"];
|
||||
NSRelationshipDescription *relationship = [entity relationshipsByName][@"friends"];
|
||||
RKConnectionMapping *connectionMapping = [[RKConnectionMapping alloc] initWithRelationship:relationship sourceKeyPath:@"housesResidedAt.ownersInChronologicalOrder" destinationKeyPath:nil matcher:nil];
|
||||
RKConnectionDescription *connection = [[RKConnectionDescription alloc] initWithRelationship:relationship keyPath:@"housesResidedAt.ownersInChronologicalOrder"];
|
||||
|
||||
RKHuman *human = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:nil withProperties:nil];
|
||||
|
||||
@@ -152,7 +155,7 @@
|
||||
human.housesResidedAt = [NSOrderedSet orderedSetWithObjects:house1, house2, nil];
|
||||
|
||||
RKFetchRequestManagedObjectCache *managedObjectCache = [RKFetchRequestManagedObjectCache new];
|
||||
RKRelationshipConnectionOperation *operation = [[RKRelationshipConnectionOperation alloc] initWithManagedObject:human connectionMapping:connectionMapping managedObjectCache:managedObjectCache];
|
||||
RKConnectionOperation *operation = [[RKConnectionOperation alloc] initWithManagedObject:human connection:connection managedObjectCache:managedObjectCache];
|
||||
[operation start];
|
||||
|
||||
NSSet *expectedFriends = [NSSet setWithObjects:homeowner1, homeowner2, homeowner3, homeowner4, nil];
|
||||
@@ -164,7 +167,7 @@
|
||||
{
|
||||
NSEntityDescription *entity = [[[RKTestFactory managedObjectStore] managedObjectModel] entitiesByName][@"Human"];
|
||||
NSRelationshipDescription *relationship = [entity relationshipsByName][@"friendsInTheOrderWeMet"];
|
||||
RKConnectionMapping *connectionMapping = [[RKConnectionMapping alloc] initWithRelationship:relationship sourceKeyPath:@"housesResidedAt.ownersInChronologicalOrder" destinationKeyPath:nil matcher:nil];
|
||||
RKConnectionDescription *connection = [[RKConnectionDescription alloc] initWithRelationship:relationship keyPath:@"housesResidedAt.ownersInChronologicalOrder"];
|
||||
|
||||
RKHuman *human = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:nil withProperties:nil];
|
||||
|
||||
@@ -182,7 +185,7 @@
|
||||
human.housesResidedAt = [NSOrderedSet orderedSetWithObjects:house1, house2, nil];
|
||||
|
||||
RKFetchRequestManagedObjectCache *managedObjectCache = [RKFetchRequestManagedObjectCache new];
|
||||
RKRelationshipConnectionOperation *operation = [[RKRelationshipConnectionOperation alloc] initWithManagedObject:human connectionMapping:connectionMapping managedObjectCache:managedObjectCache];
|
||||
RKConnectionOperation *operation = [[RKConnectionOperation alloc] initWithManagedObject:human connection:connection managedObjectCache:managedObjectCache];
|
||||
[operation start];
|
||||
|
||||
NSOrderedSet *expectedFriends = [NSOrderedSet orderedSetWithObjects:homeowner1, homeowner2, homeowner3, homeowner4, nil];
|
||||
@@ -193,12 +196,12 @@
|
||||
{
|
||||
NSEntityDescription *entity = [[[RKTestFactory managedObjectStore] managedObjectModel] entitiesByName][@"Human"];
|
||||
NSRelationshipDescription *relationship = [entity relationshipsByName][@"friendsInTheOrderWeMet"];
|
||||
RKConnectionMapping *connectionMapping = [[RKConnectionMapping alloc] initWithRelationship:relationship sourceKeyPath:@"housesResidedAt.ownersInChronologicalOrder" destinationKeyPath:nil matcher:nil];
|
||||
RKConnectionDescription *connection = [[RKConnectionDescription alloc] initWithRelationship:relationship keyPath:@"housesResidedAt.ownersInChronologicalOrder"];
|
||||
|
||||
RKHuman *human = [RKTestFactory insertManagedObjectForEntityForName:@"Human" inManagedObjectContext:nil withProperties:nil];
|
||||
|
||||
RKFetchRequestManagedObjectCache *managedObjectCache = [RKFetchRequestManagedObjectCache new];
|
||||
RKRelationshipConnectionOperation *operation = [[RKRelationshipConnectionOperation alloc] initWithManagedObject:human connectionMapping:connectionMapping managedObjectCache:managedObjectCache];
|
||||
RKConnectionOperation *operation = [[RKConnectionOperation alloc] initWithManagedObject:human connection:connection managedObjectCache:managedObjectCache];
|
||||
[operation start];
|
||||
|
||||
expect([human.friendsInTheOrderWeMet set]).to.beEmpty();
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
// Copyright (c) 2012 RestKit. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Kiwi.h"
|
||||
#import "RKTestEnvironment.h"
|
||||
#import "RKTestUser.h"
|
||||
#import "Specta.h"
|
||||
|
||||
SPEC_BEGIN(RKResponseDescriptorSpec)
|
||||
SpecBegin(RKResponseDescriptorSpec)
|
||||
|
||||
describe(@"matchesURL:", ^{
|
||||
__block NSURL *baseURL;
|
||||
@@ -28,9 +28,9 @@ describe(@"matchesURL:", ^{
|
||||
responseDescriptor.baseURL = baseURL;
|
||||
});
|
||||
|
||||
it(@"returns YES", ^{
|
||||
it(@"returns YES", ^{
|
||||
NSURL *URL = [NSURL URLWithString:@"http://restkit.org/monkeys/1234.json"];
|
||||
[[@([responseDescriptor matchesURL:URL]) should] beYes];
|
||||
expect([responseDescriptor matchesURL:URL]).to.equal(YES);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -44,14 +44,14 @@ describe(@"matchesURL:", ^{
|
||||
context(@"and given a URL in which the path and query string match the path pattern", ^{
|
||||
it(@"returns YES", ^{
|
||||
NSURL *URL = [NSURL URLWithString:@"http://restkit.org/monkeys/1234.json"];
|
||||
[[@([responseDescriptor matchesURL:URL]) should] beYes];
|
||||
expect([responseDescriptor matchesURL:URL]).to.equal(YES);
|
||||
});
|
||||
});
|
||||
|
||||
context(@"and given a URL in which the path and query string do match the path pattern", ^{
|
||||
it(@"returns NO", ^{
|
||||
NSURL *URL = [NSURL URLWithString:@"http://restkit.org/mismatch"];
|
||||
[[@([responseDescriptor matchesURL:URL]) should] beNo];
|
||||
expect([responseDescriptor matchesURL:URL]).to.equal(NO);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -72,20 +72,20 @@ describe(@"matchesURL:", ^{
|
||||
context(@"and given the URL 'http://google.com/monkeys/1234.json'", ^{
|
||||
it(@"returns NO", ^{
|
||||
NSURL *URL = [NSURL URLWithString:@"http://google.com/monkeys/1234.json"];
|
||||
[[@([responseDescriptor matchesURL:URL]) should] beNo];
|
||||
expect([responseDescriptor matchesURL:URL]).to.equal(NO);
|
||||
});
|
||||
});
|
||||
|
||||
context(@"and given the URL 'http://restkit.org/whatever", ^{
|
||||
it(@"returns YES", ^{
|
||||
NSURL *URL = [NSURL URLWithString:@"http://restkit.org/whatever"];
|
||||
[[@([responseDescriptor matchesURL:URL]) should] beYes];
|
||||
expect([responseDescriptor matchesURL:URL]).to.equal(YES);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context(@"and the path pattern is '/monkeys/:monkeyID\\.json'", ^{
|
||||
beforeEach(^{
|
||||
beforeEach(^{
|
||||
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
|
||||
responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:@"/monkeys/:monkeyID\\.json" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
|
||||
responseDescriptor.baseURL = baseURL;
|
||||
@@ -95,7 +95,7 @@ describe(@"matchesURL:", ^{
|
||||
it(@"returns NO", ^{
|
||||
NSURL *otherBaseURL = [NSURL URLWithString:@"http://google.com"];
|
||||
NSURL *URL = [NSURL URLWithString:@"/monkeys/1234.json" relativeToURL:otherBaseURL];
|
||||
[[@([responseDescriptor matchesURL:URL]) should] beNo];
|
||||
expect([responseDescriptor matchesURL:URL]).to.equal(NO);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -103,21 +103,21 @@ describe(@"matchesURL:", ^{
|
||||
context(@"in which the path and query string match the path pattern", ^{
|
||||
it(@"returns YES", ^{
|
||||
NSURL *URL = [NSURL URLWithString:@"/monkeys/1234.json" relativeToURL:baseURL];
|
||||
[[@([responseDescriptor matchesURL:URL]) should] beYes];
|
||||
expect([responseDescriptor matchesURL:URL]).to.equal(YES);
|
||||
});
|
||||
});
|
||||
|
||||
context(@"in which the path and query string do match the path pattern", ^{
|
||||
it(@"returns NO", ^{
|
||||
NSURL *URL = [NSURL URLWithString:@"/mismatch" relativeToURL:baseURL];
|
||||
[[@([responseDescriptor matchesURL:URL]) should] beNo];
|
||||
expect([responseDescriptor matchesURL:URL]).to.equal(NO);
|
||||
});
|
||||
});
|
||||
|
||||
context(@"and the URL includes a query string", ^{
|
||||
it(@"returns NO", ^{
|
||||
NSURL *URL = [NSURL URLWithString:@"/monkeys/1234.json?param1=val1¶m2=val2" relativeToURL:baseURL];
|
||||
[[@([responseDescriptor matchesURL:URL]) should] beYes];
|
||||
expect([responseDescriptor matchesURL:URL]).to.equal(YES);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -139,15 +139,15 @@ describe(@"matchesURL:", ^{
|
||||
context(@"and given the URL 'http://0.0.0.0:5000/api/v1/organizations/?client_search=t'", ^{
|
||||
it(@"returns YES", ^{
|
||||
NSURL *URL = [NSURL URLWithString:@"http://0.0.0.0:5000/api/v1/organizations/?client_search=t"];
|
||||
[[@([responseDescriptor matchesURL:URL]) should] beYes];
|
||||
expect([responseDescriptor matchesURL:URL]).to.equal(YES);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
context(@"when the baseURL is 'http://restkit.org/api/v1/'", ^{
|
||||
beforeEach(^{
|
||||
baseURL = [NSURL URLWithString:@"http://restkit.org/api/v1/"];
|
||||
baseURL = [NSURL URLWithString:@"http://restkit.org/api/v1/"];
|
||||
});
|
||||
|
||||
context(@"and the path pattern is nil", ^{
|
||||
@@ -160,14 +160,14 @@ describe(@"matchesURL:", ^{
|
||||
context(@"and given the URL 'http://google.com/monkeys/api/v1/1234.json'", ^{
|
||||
it(@"returns NO", ^{
|
||||
NSURL *URL = [NSURL URLWithString:@"http://restkit.org/monkeys/1234.json"];
|
||||
[[@([responseDescriptor matchesURL:URL]) should] beNo];
|
||||
expect([responseDescriptor matchesURL:URL]).to.equal(NO);
|
||||
});
|
||||
});
|
||||
|
||||
context(@"and given the URL 'http://restkit.org/api/v1/whatever", ^{
|
||||
it(@"returns YES", ^{
|
||||
NSURL *URL = [NSURL URLWithString:@"http://restkit.org/api/v1/whatever"];
|
||||
[[@([responseDescriptor matchesURL:URL]) should] beYes];
|
||||
expect([responseDescriptor matchesURL:URL]).to.equal(YES);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -181,7 +181,7 @@ describe(@"matchesURL:", ^{
|
||||
|
||||
NSURL *otherBaseURL = [NSURL URLWithString:@"http://google.com"];
|
||||
NSURL *URL = [NSURL URLWithString:@"monkeys/1234.json" relativeToURL:otherBaseURL];
|
||||
[[@([responseDescriptor matchesURL:URL]) should] beNo];
|
||||
expect([responseDescriptor matchesURL:URL]).to.equal(NO);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -197,14 +197,14 @@ describe(@"matchesURL:", ^{
|
||||
context(@"in which the path and query string match the path pattern", ^{
|
||||
it(@"returns YES", ^{
|
||||
NSURL *URL = [NSURL URLWithString:@"monkeys/1234.json" relativeToURL:baseURL];
|
||||
[[@([responseDescriptor matchesURL:URL]) should] beYes];
|
||||
expect([responseDescriptor matchesURL:URL]).to.equal(YES);
|
||||
});
|
||||
});
|
||||
|
||||
context(@"in which the path and query string do match the path pattern", ^{
|
||||
it(@"returns NO", ^{
|
||||
NSURL *URL = [NSURL URLWithString:@"mismatch" relativeToURL:baseURL];
|
||||
[[@([responseDescriptor matchesURL:URL]) should] beNo];
|
||||
expect([responseDescriptor matchesURL:URL]).to.equal(NO);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -213,14 +213,14 @@ describe(@"matchesURL:", ^{
|
||||
context(@"in which the path and query string match the path pattern", ^{
|
||||
it(@"returns YES", ^{
|
||||
NSURL *URL = [NSURL URLWithString:@"http://restkit.org/api/v1/monkeys/1234.json"];
|
||||
[[@([responseDescriptor matchesURL:URL]) should] beYes];
|
||||
expect([responseDescriptor matchesURL:URL]).to.equal(YES);
|
||||
});
|
||||
});
|
||||
|
||||
context(@"in which the path and query string do match the path pattern", ^{
|
||||
it(@"returns NO", ^{
|
||||
NSURL *URL = [NSURL URLWithString:@"http://restkit.org/api/v1/mismatch"];
|
||||
[[@([responseDescriptor matchesURL:URL]) should] beNo];
|
||||
expect([responseDescriptor matchesURL:URL]).to.equal(NO);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -245,7 +245,7 @@ describe(@"matchesResponse:", ^{
|
||||
it(@"returns YES", ^{
|
||||
NSURL *URL = [NSURL URLWithString:@"http://0.0.0.0:5000/api/v1/organizations/?client_search=t"];
|
||||
NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:URL statusCode:200 HTTPVersion:@"1.1" headerFields:nil];
|
||||
[[@([responseDescriptor matchesResponse:response]) should] beYes];
|
||||
expect([responseDescriptor matchesResponse:response]).to.equal(YES);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -263,7 +263,7 @@ describe(@"matchesResponse:", ^{
|
||||
it(@"returns NO", ^{
|
||||
NSURL *URL = [NSURL URLWithString:@"http://domain.com/domain/api/v1/recommendation/"];
|
||||
NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:URL statusCode:200 HTTPVersion:@"1.1" headerFields:nil];
|
||||
[[@([responseDescriptor matchesResponse:response]) should] beNo];
|
||||
expect([responseDescriptor matchesResponse:response]).to.equal(NO);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -277,11 +277,11 @@ describe(@"matchesResponse:", ^{
|
||||
it(@"returns NO", ^{
|
||||
NSURL *URL = [NSURL URLWithString:@"http://domain.com/domain/api/v1/recommendation?action=search&type=whatever"];
|
||||
NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:URL statusCode:200 HTTPVersion:@"1.1" headerFields:nil];
|
||||
[[@([responseDescriptor matchesResponse:response]) should] beNo];
|
||||
expect([responseDescriptor matchesResponse:response]).to.equal(NO);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
SPEC_END
|
||||
SpecEnd
|
||||
|
||||
@@ -361,7 +361,7 @@
|
||||
{
|
||||
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
|
||||
mapping.forceCollectionMapping = YES;
|
||||
[mapping mapKeyOfNestedDictionaryToAttribute:@"name"];
|
||||
[mapping addAttributeMappingFromKeyOfRepresentationToAttribute:@"name"];
|
||||
RKAttributeMapping *idMapping = [RKAttributeMapping attributeMappingFromKeyPath:@"(name).id" toKeyPath:@"userID"];
|
||||
[mapping addPropertyMapping:idMapping];
|
||||
NSMutableDictionary *mappingsDictionary = [NSMutableDictionary dictionary];
|
||||
@@ -386,7 +386,7 @@
|
||||
{
|
||||
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
|
||||
mapping.forceCollectionMapping = YES;
|
||||
[mapping mapKeyOfNestedDictionaryToAttribute:@"name"];
|
||||
[mapping addAttributeMappingFromKeyOfRepresentationToAttribute:@"name"];
|
||||
|
||||
RKObjectMapping *addressMapping = [RKObjectMapping mappingForClass:[RKTestAddress class]];
|
||||
[addressMapping addAttributeMappingsFromArray:@[@"city", @"state"]];
|
||||
@@ -419,7 +419,7 @@
|
||||
|
||||
RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
|
||||
userMapping.forceCollectionMapping = YES;
|
||||
[userMapping mapKeyOfNestedDictionaryToAttribute:@"name"];
|
||||
[userMapping addAttributeMappingFromKeyOfRepresentationToAttribute:@"name"];
|
||||
[mapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"users" toKeyPath:@"users" withMapping:userMapping]];;
|
||||
|
||||
RKObjectMapping *addressMapping = [RKObjectMapping mappingForClass:[RKTestAddress class]];
|
||||
@@ -475,7 +475,7 @@
|
||||
|
||||
RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RKTestUser class]];
|
||||
userMapping.forceCollectionMapping = YES;
|
||||
[userMapping mapKeyOfNestedDictionaryToAttribute:@"name"];
|
||||
[userMapping addAttributeMappingFromKeyOfRepresentationToAttribute:@"name"];
|
||||
[mapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"users" toKeyPath:@"users" withMapping:userMapping]];;
|
||||
|
||||
RKObjectMapping *addressMapping = [RKObjectMapping mappingForClass:[RKTestAddress class]];
|
||||
@@ -2037,7 +2037,7 @@
|
||||
NSArray *array = [RKTestFixture parsedObjectWithContentsOfFixture:@"ArrayOfHumans.json"];
|
||||
RKEntityMapping *humanMapping = [RKEntityMapping mappingForEntityForName:@"Human" inManagedObjectStore:managedObjectStore];
|
||||
[humanMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"id" toKeyPath:@"railsID"]];
|
||||
[humanMapping setEntityIdentifierWithAttributes:@"railsID"];
|
||||
humanMapping.entityIdentifier = [RKEntityIdentifier identifierWithEntityName:@"Human" attributes:@[ @"railsID" ] inManagedObjectStore:managedObjectStore];
|
||||
NSMutableDictionary *mappingsDictionary = [NSMutableDictionary dictionary];
|
||||
[mappingsDictionary setObject:humanMapping forKey:@"human"];
|
||||
|
||||
|
||||
@@ -175,7 +175,7 @@
|
||||
- (void)testPropertyNameTransformationBlockForAttributes
|
||||
{
|
||||
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
|
||||
[mapping setSourceToDestinationKeyTransformationBlock:^NSString *(NSString *sourceKey) {
|
||||
[mapping setSourceToDestinationKeyTransformationBlock:^NSString *(RKObjectMapping *mapping, NSString *sourceKey) {
|
||||
return [sourceKey uppercaseString];
|
||||
}];
|
||||
[mapping addAttributeMappingsFromArray:@[ @"name", @"rank" ]];
|
||||
@@ -186,7 +186,7 @@
|
||||
- (void)testPropertyNameTransformationBlockForRelationships
|
||||
{
|
||||
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
|
||||
[mapping setSourceToDestinationKeyTransformationBlock:^NSString *(NSString *sourceKey) {
|
||||
[mapping setSourceToDestinationKeyTransformationBlock:^NSString *(RKObjectMapping *mapping, NSString *sourceKey) {
|
||||
return [sourceKey uppercaseString];
|
||||
}];
|
||||
RKObjectMapping *relatedMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
|
||||
@@ -200,7 +200,7 @@
|
||||
- (void)testTransformationOfAttributeKeyPaths
|
||||
{
|
||||
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
|
||||
[mapping setSourceToDestinationKeyTransformationBlock:^NSString *(NSString *sourceKey) {
|
||||
[mapping setSourceToDestinationKeyTransformationBlock:^NSString *(RKObjectMapping *mapping, NSString *sourceKey) {
|
||||
return [sourceKey capitalizedString];
|
||||
}];
|
||||
[mapping addAttributeMappingsFromArray:@[ @"user.comments" ]];
|
||||
@@ -210,7 +210,7 @@
|
||||
|
||||
- (void)testDefaultSourceToDestinationKeyTransformationBlock
|
||||
{
|
||||
[RKObjectMapping setDefaultSourceToDestinationKeyTransformationBlock:^NSString *(NSString *sourceKey) {
|
||||
[RKObjectMapping setDefaultSourceToDestinationKeyTransformationBlock:^NSString *(RKObjectMapping *mapping, NSString *sourceKey) {
|
||||
return [sourceKey capitalizedString];
|
||||
}];
|
||||
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
}
|
||||
@finally {
|
||||
assertThat(exception, is(notNilValue()));
|
||||
assertThat(exception.reason, containsString(@"Invalid attribute identifier given: No attribute with the name 'doesNotExist' found in the 'RKHuman' entity."));
|
||||
assertThat(exception.reason, containsString(@"Invalid attribute identifier given: No attribute with the name 'doesNotExist' found in the 'Human' entity."));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user