Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
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.