34 #import <ActiveSupportKit/ActiveSupportKit.h>
38 - (id)executeFetchRequest:(NSFetchRequest *)request withContext:(NSManagedObjectContext *)context error:(NSError **)outError;
40 - (id)executeSaveRequest:(NSSaveChangesRequest *)request withContext:(NSManagedObjectContext *)context error:(NSError **)outError;
64 + (NSString *)storeTypeForClass:(Class)aClass
66 return NSStringFromClass(aClass);
69 + (void)registerStoreTypeForClass:(Class)aClass
71 [NSPersistentStoreCoordinator registerStoreClass:aClass forStoreType:[
self storeTypeForClass:aClass]];
75 - (id)initWithPersistentStoreCoordinator:(NSPersistentStoreCoordinator *)root configurationName:(NSString *)name URL:(NSURL *)URL options:(NSDictionary *)options
77 self = [
super initWithPersistentStoreCoordinator:root configurationName:name URL:URL options:options];
82 [
self setEntityNamePrefix:[options objectForKey:ARIncrementalStoreElementNamePrefixKey]];
87 - (
ARService *)serviceForEntityName:(NSString *)entityName
103 #pragma mark Active Resource-to-Core Data Names
108 - (NSString *)elementNameForEntityName:(NSString *)entityName
117 entityName = [entityName substringFromIndex:[[
self entityNamePrefix] length]];
119 return [[ASInflector defaultInflector] underscore:entityName];
122 - (NSString *)entityNameForElementName:(NSString *)elementName
124 NSString *entityName = [[ASInflector defaultInflector] camelize:elementName uppercaseFirstLetter:YES];
132 - (NSString *)attributeNameForPropertyName:(NSString *)propertyName
134 return [[ASInflector defaultInflector] underscore:propertyName];
137 - (NSString *)propertyNameForAttributeName:(NSString *)attributeName
139 return [[ASInflector defaultInflector] camelize:attributeName uppercaseFirstLetter:NO];
143 #pragma mark Incremental Store Method Overrides
155 - (BOOL)loadMetadata:(NSError **)outError
157 NSMutableDictionary *metadata = [NSMutableDictionary dictionary];
165 [metadata setObject:[[
self URL] description] forKey:NSStoreUUIDKey];
167 [
self setMetadata:[metadata copy]];
171 - (id)executeRequest:(NSPersistentStoreRequest *)request withContext:(NSManagedObjectContext *)context error:(NSError **)outError
173 switch ([request requestType])
175 case NSFetchRequestType:
177 case NSSaveRequestType:
233 - (id)executeFetchRequest:(NSFetchRequest *)request withContext:(NSManagedObjectContext *)context error:(NSError **)outError
235 id __block result = nil;
237 NSMutableDictionary *options = [NSMutableDictionary dictionary];
238 NSUInteger fetchLimit = [request fetchLimit];
241 [options setValue:[NSNumber numberWithUnsignedInteger:fetchLimit] forKey:@"limit"];
243 NSUInteger fetchOffset = [request fetchOffset];
246 [options setValue:[NSNumber numberWithUnsignedInteger:fetchOffset] forKey:@"offset"];
274 NSMutableArray *orderStrings = [NSMutableArray array];
275 for (NSSortDescriptor *sortDescriptor in [request sortDescriptors])
277 [orderStrings addObject:[NSString stringWithFormat:@"%@+%@", [
self attributeNameForPropertyName:[sortDescriptor key]], [sortDescriptor ascending] ? @"asc" : @"desc"]];
279 if ([orderStrings count])
281 [options setObject:[orderStrings componentsJoinedByString:@","] forKey:@"order"];
283 [[
self serviceForEntityName:[request entityName]] findAllWithOptions:options completionHandler:^(ARHTTPResponse *response, NSArray *resources, NSError *error) {
291 NSMutableArray *objectIDs = [NSMutableArray array];
292 for (ARResource *resource in resources)
300 switch ([request resultType])
302 case NSManagedObjectResultType:
303 result = [NSMutableArray array];
304 for (NSManagedObjectID *objectID in objectIDs)
306 [(NSMutableArray *)result addObject:[context objectWithID:objectID]];
308 result = [result copy];
310 case NSManagedObjectIDResultType:
311 result = [NSMutableArray array];
312 for (NSManagedObjectID *objectID in objectIDs)
314 [(NSMutableArray *)result addObject:objectID];
316 result = [result copy];
318 case NSCountResultType:
319 result = [NSArray arrayWithObject:[NSNumber numberWithUnsignedInteger:[objectIDs count]]];
331 if (outError && *outError == nil)
346 - (id)executeSaveRequest:(NSSaveChangesRequest *)request withContext:(NSManagedObjectContext *)context error:(NSError **)outError
348 NSMutableArray *errors = [NSMutableArray array];
358 for (NSManagedObject *
object in [[request insertedObjects] copy])
364 if ([foreignKeys count])
374 [errors addObject:error];
391 for (NSManagedObject *
object in [[request updatedObjects] copy])
405 NSEntityDescription *entity = [object entity];
425 NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithDictionary:[entity attributesFromObject:object]];
427 if ([attributes isEqualToDictionary:[[resource attributes] dictionaryWithValuesForKeys:[attributes allKeys]]])
432 [resource setPersisted:YES];
440 [errors addObject:error];
446 for (NSManagedObject *
object in [[request deletedObjects] copy])
448 NSNumber *ID = [
self referenceObjectForObjectID:[object objectID]];
449 NSEntityDescription *entity = [object entity];
458 [errors addObject:error];
464 BOOL success = [errors count] == 0;
465 if (!success && outError && *outError == nil)
467 *outError = [errors objectAtIndex:0];
469 return success ? [NSArray array] : nil;
472 - (NSIncrementalStoreNode *)newValuesForObjectWithID:(NSManagedObjectID *)objectID withContext:(NSManagedObjectContext *)context error:(NSError **)outError
477 NSIncrementalStoreNode *node;
488 NSMutableDictionary *properties = [NSMutableDictionary dictionaryWithDictionary:[[objectID entity] propertiesFromResource:resource]];
489 [properties removeObjectsForKeys:[properties allKeysForObject:[NSNull null]]];
491 node = [[NSIncrementalStoreNode alloc] initWithObjectID:objectID withValues:[properties copy] version:version];
496 if (outError && *outError == nil)
498 *outError = [NSError errorWithDomain:ARErrorDomain code:ARValuesForObjectError userInfo:nil];
504 - (id)newValueForRelationship:(NSRelationshipDescription *)relationship forObjectWithID:(NSManagedObjectID *)objectID withContext:(NSManagedObjectContext *)context error:(NSError **)outError
508 if ([relationship maxCount] == 1)
523 NSString *foreignKey = [[ASInflector defaultInflector] foreignKey:relationshipName separateClassNameAndIDWithUnderscore:YES];
524 id foreignID = ASNilForNull([[resource attributes] objectForKey:foreignKey]);
525 if (foreignID == nil)
527 foreignID = [[resource
prefixOptions] objectForKey:foreignKey];
529 if (foreignID == nil)
531 result = [NSNull null];
535 result = [
self newObjectIDForEntity:[relationship destinationEntity] referenceObject:foreignID];
539 else if ([relationship isToMany])
558 [nestedService setElementName:[[ASInflector defaultInflector] singularize:[relationship name]]];
560 NSDictionary *options = [NSDictionary dictionaryWithObject:[
self referenceObjectForObjectID:objectID] forKey:[service
foreignKey]];
564 NSMutableArray *objectIDs = [NSMutableArray array];
565 for (ARResource *resource in resources)
569 result = [objectIDs copy];
574 if (outError && *outError == nil)
584 if (outError && *outError == nil)
586 *outError = [NSError errorWithDomain:ARErrorDomain code:ARValueForRelationshipError userInfo:nil];
607 - (NSArray *)obtainPermanentIDsForObjects:(NSArray *)objects error:(NSError **)outError
609 NSMutableArray *objectIDs = [NSMutableArray array];
610 NSMutableArray *errors = [NSMutableArray array];
611 for (NSManagedObject *
object in objects)
613 NSEntityDescription *entity = [object entity];
618 NSManagedObjectID *objectID = [
self newObjectIDForEntity:entity referenceObject:[resource
ID]];
620 [objectIDs addObject:objectID];
628 [objectIDs addObject:[NSNull null]];
629 [errors addObject:error];
633 BOOL success = [errors count] == 0;
634 if (!success && outError && *outError == nil)
636 *outError = [errors objectAtIndex:0];
638 return success ? [objectIDs copy] : nil;
641 - (void)cache:(NSCache *)cache willEvictObject:(
id)obj