Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Dropping in OTRest code changes from work on GateGuru. Model mapping …

…object creation has some serious issues...
  • Loading branch information...
commit 9c1c6d2f9a9129cc8b3bb13217fdf3adcc20054f 1 parent 5292554
Blake Watters authored
View
7 OTRestManagedModel.h
@@ -45,11 +45,16 @@
+ (id)newObject;
/**
- * The primaryKey property mapping, defaults to @"id" for Rails generated XML
+ * The primaryKey property mapping, defaults to @"ID"
*/
+ (NSString*)primaryKey;
/**
+ * The name of the primary key in the server-side data payload. Defaults to @"id" for Rails generated XML/JSON
+ */
++ (NSString*)primaryKeyElement;
+
+/**
* Will find the existing object with the primary key of 'value' and return it
* or return nil
*/
View
25 OTRestManagedModel.m
@@ -34,6 +34,7 @@ + (NSFetchRequest*)request {
+ (NSArray*)collectionWithRequest:(NSFetchRequest*)request {
NSError* error = nil;
+ NSLog(@"About to perform a collection request: %@", request);
NSArray* collection = [[self managedObjectContext] executeFetchRequest:request error:&error];
if (error != nil) {
NSLog(@"Error: %@", [error localizedDescription]);
@@ -71,24 +72,37 @@ + (NSArray*)allObjects {
#pragma mark -
#pragma mark OTRestModelMappable
+// TODO: All this path shit needs cleaning up...
- (NSString*)resourcePath {
[self doesNotRecognizeSelector:_cmd];
return nil;
}
+// TODO: The .xml format should NOT be specified here!
+- (NSString*)collectionPath {
+ return [NSString stringWithFormat:@"%@.xml", [self resourcePath]];
+}
+
+- (NSString*)memberPath {
+ NSLog(@"Was asked for memberPath. primaryKeyValue is %@. self = %@", [self valueForKey:[[self class] primaryKey]], self);
+ return [NSString stringWithFormat:@"%@/%@.xml", [self resourcePath], [self valueForKey:[[self class] primaryKey]]];
+}
+
+ (id)newObject {
id model = [[self alloc] initWithEntity:[self entity] insertIntoManagedObjectContext:[self managedObjectContext]];
return [model autorelease];
}
+ (NSString*)primaryKey {
+ return @"ID";
+}
+
++ (NSString*)primaryKeyElement {
return @"id";
}
+ (id)findByPrimaryKey:(id)value {
- NSString* pk = [[[self elementToPropertyMappings] objectForKey:[self primaryKey]] retain];
- NSPredicate* predicate = [NSPredicate predicateWithFormat:@"%K = %@", pk, value];
- [pk release];
+ NSPredicate* predicate = [NSPredicate predicateWithFormat:@"%K = %@", [self primaryKey], value];
return [self objectWithPredicate:predicate];
}
@@ -129,6 +143,7 @@ - (NSDictionary*)elementNamesAndPropertyValues {
return (NSDictionary*) elementsAndPropertyValues;
}
+// TODO: This implementation is Rails specific. Consider using an adapter approach.
- (NSDictionary*)resourceParams {
NSDictionary* elementsAndProperties = [self elementNamesAndPropertyValues];
NSMutableDictionary* resourceParams = [NSMutableDictionary dictionaryWithCapacity:[elementsAndProperties count]];
@@ -143,6 +158,7 @@ - (NSDictionary*)resourceParams {
return resourceParams;
}
+// TODO: Should this handle persistence to the web also? Should the model manager do it instead? How do we handle deletes? creation? need flags?
- (NSError*)save {
NSError* error = nil;
[[self managedObjectContext] save:&error];
@@ -152,7 +168,8 @@ - (NSError*)save {
return error;
}
-- (void)destroy {
+// TODO: Delete on the server also? See above.
+- (void)destroy {
[[self managedObjectContext] deleteObject:self];
}
View
4 OTRestModelLoader.m
@@ -30,7 +30,9 @@ - (SEL)collectionCallback {
}
- (void)loadModelFromResponse:(OTRestResponse*)response {
- id model = [_mapper buildModelFromString:[response payloadString]];
+ NSLog(@"Attempting to build model from response: %@", [response payloadString]);
+ // TODO: This needs to handle errors!!!
+ id model = [_mapper buildModelFromString:[response payloadString]];
[_delegate performSelector:self.callback withObject:model];
}
View
8 OTRestModelManager.m
@@ -87,7 +87,7 @@ - (OTRestRequest*)getModel:(id<OTRestModelMappable>)model delegate:(id)delegate
loader.delegate = delegate;
loader.callback = callback;
- return [_client get:[model resourcePath] delegate:loader callback:loader.memberCallback];
+ return [_client get:[model memberPath] delegate:loader callback:loader.memberCallback];
}
- (OTRestRequest*)postModel:(id<OTRestModelMappable>)model delegate:(id)delegate callback:(SEL)callback {
@@ -96,7 +96,7 @@ - (OTRestRequest*)postModel:(id<OTRestModelMappable>)model delegate:(id)delegate
loader.callback = callback;
OTRestParams* params = [OTRestParams paramsWithDictionary:[model resourceParams]];
- return [_client post:[model resourcePath] params:params delegate:loader callback:loader.memberCallback];
+ return [_client post:[model collectionPath] params:params delegate:loader callback:loader.memberCallback];
}
- (OTRestRequest*)putModel:(id<OTRestModelMappable>)model delegate:(id)delegate callback:(SEL)callback {
@@ -105,13 +105,13 @@ - (OTRestRequest*)putModel:(id<OTRestModelMappable>)model delegate:(id)delegate
loader.callback = callback;
OTRestParams* params = [OTRestParams paramsWithDictionary:[model resourceParams]];
- return [_client put:[model resourcePath] params:params delegate:loader callback:loader.memberCallback];
+ return [_client put:[model memberPath] params:params delegate:loader callback:loader.memberCallback];
}
- (OTRestRequest*)deleteModel:(id<OTRestModelMappable>)model delegate:(id)delegate callback:(SEL)callback {
// TODO: are we responsible for deleting the object too,
// or are we to assume that the caller has/will delete it?
- return [_client delete:[model resourcePath] delegate:delegate callback:callback];
+ return [_client delete:[model memberPath] delegate:delegate callback:callback];
}
@end
View
12 OTRestModelMapper.m
@@ -6,7 +6,8 @@
// Copyright 2009 Objective 3. All rights reserved.
//
-#import <objc/objc-runtime.h>
+// #import <objc/objc-runtime.h>
+#import <objc/message.h>
#import "OTRestModelMapper.h"
#import "OTRestModelMapper_Private.h"
#import "ElementParser.h"
@@ -86,8 +87,7 @@ - (void)updateObject:(id)model ifNewPropertyPropertyValue:(id)propertyValue forP
* The logic below is so that we don't trigger KVO observers
* when we aren't actually changing values
*/
- if (currentValue == nil &&
- propertyValue == nil) {
+ if (currentValue == nil && propertyValue == nil) {
} else if (currentValue == nil) {
[model setValue:propertyValue forKey:propertyName];
} else {
@@ -99,7 +99,7 @@ - (void)updateObject:(id)model ifNewPropertyPropertyValue:(id)propertyValue forP
} else if ([propertyValue isKindOfClass:[NSDate class]]) {
comparisonSelector = @selector(isEqualToDate:);
} else {
- [NSException raise:@"NoComparisonSelectorFound" format:@"You need a comparison selector for %@", [propertyValue class]];
+ [NSException raise:@"NoComparisonSelectorFound" format:@"You need a comparison selector for %@ (%@)", propertyName, [propertyValue class]];
}
// Comparison magic using function pointers. See this page for details: http://www.red-sweater.com/blog/320/abusing-objective-c-with-class
@@ -224,6 +224,7 @@ - (id)buildModelFromXML:(Element*)XML {
NSString* elementName = [XML key];
Class class = [_elementToClassMappings objectForKey:elementName];
if (class == nil) {
+ NSLog(@"Encountered an unmapped class while processing XML Element: %@", XML);
[NSException raise:@"NoClassMappingForModel" format:@"No Class Mapping for Element name '%@'", elementName];
}
id object = [self createOrUpdateInstanceOf:class fromXML:XML];
@@ -235,7 +236,8 @@ - (id)createOrUpdateInstanceOf:(Class)class fromXML:(Element*)XML {
// Find by PK, if it responds to it
if ([class respondsToSelector:@selector(findByPrimaryKey:)]) {
// TODO: factor to class method? incase it is not a number
- NSNumber* pk = [XML contentsNumberOfChildElement:[class primaryKey]];
+ NSNumber* pk = [XML contentsNumberOfChildElement:[class primaryKeyElement]];
+ NSLog(@"Attempting to find object by primary key %@ via primaryKeyElement %@", pk, [class primaryKeyElement]);
object = [class findByPrimaryKey:pk];
}
// instantiate if object is nil
View
8 OTRestParams.m
@@ -94,8 +94,14 @@ - (void)addValuesToHTTPBody:(NSMutableData*)HTTPBody {
int i = 0;
for (id key in _valueData) {
id value = [_valueData valueForKey:key];
+ NSLog(@"Attempting to add HTTP param named %@ with type %@ and value %@", key, [value class], value);
[HTTPBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]];
- [HTTPBody appendData:[value dataUsingEncoding:NSUTF8StringEncoding]];
+ // TODO: Can get _PFCachedNumber objects back from valueForKey: from Core Data. Need to figure this out...
+ if ([value respondsToSelector:@selector(dataUsingEncoding:)]) {
+ [HTTPBody appendData:[value dataUsingEncoding:NSUTF8StringEncoding]];
+ } else {
+ [HTTPBody appendData:[[NSString stringWithFormat:@"%@", value] dataUsingEncoding:NSUTF8StringEncoding]];
+ }
i++;
// Only add the boundary if this is not the last item in the post body
Please sign in to comment.
Something went wrong with that request. Please try again.