-
Notifications
You must be signed in to change notification settings - Fork 0
/
OTRestManagedModel.m
182 lines (149 loc) · 5.38 KB
/
OTRestManagedModel.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
//
// OTManagedModel.m
// OTRestFramework
//
// Created by Blake Watters on 8/14/09.
// Copyright 2009 Two Toasters. All rights reserved.
//
#import "OTRestManagedModel.h"
#import "NSString+InflectionSupport.h"
#import <objc/runtime.h>
@implementation OTRestManagedModel
#pragma mark -
#pragma mark NSManagedObject helper methods
+ (NSManagedObjectContext*)managedObjectContext {
return [[[OTRestModelManager manager] objectStore] managedObjectContext];
}
+ (NSEntityDescription*)entity {
NSString* className = [NSString stringWithCString:class_getName([self class]) encoding:NSASCIIStringEncoding];
return [NSEntityDescription entityForName:className inManagedObjectContext:[self managedObjectContext]];
}
+ (NSFetchRequest*)request {
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [self entity];
[request setEntity:entity];
[request autorelease];
return 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]);
// TODO: Error handling
}
return collection;
}
+ (id)objectWithRequest:(NSFetchRequest*)request {
[request setFetchLimit:1];
NSArray* collection = [self collectionWithRequest:request];
if ([collection count] == 0) {
return nil;
} else {
return [collection objectAtIndex:0];
}
}
+ (NSArray*)collectionWithPredicate:(NSPredicate*)predicate {
NSFetchRequest* request = [self request];
[request setPredicate:predicate];
return [self collectionWithRequest:request];
}
+ (id)objectWithPredicate:(NSPredicate*)predicate {
NSFetchRequest* request = [self request];
[request setPredicate:predicate];
return [self objectWithRequest:request];
}
+ (NSArray*)allObjects {
return [self collectionWithPredicate:nil];
}
#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 @"railsID";
}
+ (NSString*)primaryKeyElement {
return @"id";
}
+ (id)findByPrimaryKey:(id)value {
NSPredicate* predicate = [NSPredicate predicateWithFormat:@"%K = %@", [self primaryKey], value];
return [self objectWithPredicate:predicate];
}
+ (NSDictionary*)elementToPropertyMappings {
[self doesNotRecognizeSelector:_cmd];
return nil;
}
+ (NSDictionary*)elementToRelationshipMappings {
return [NSDictionary dictionary];
}
+ (NSArray*)elementNames {
return [[self elementToPropertyMappings] allKeys];
}
+ (NSArray*)propertyNames {
return [[self elementToPropertyMappings] allValues];
}
+ (NSString*)modelName {
[self doesNotRecognizeSelector:_cmd];
return nil;
}
#pragma mark Helpers
- (NSDictionary*)elementNamesAndPropertyValues {
NSDictionary* mappings = [[self class] elementToPropertyMappings];
NSMutableDictionary* elementsAndPropertyValues = [NSMutableDictionary dictionaryWithCapacity:[mappings count]];
// Return all the properties of this model in a dictionary under their element names
for (NSString* elementName in mappings) {
NSString* propertyName = [mappings valueForKey:elementName];
id propertyValue = [self valueForKey:propertyName];
[elementsAndPropertyValues setValue:propertyValue forKey:elementName];
}
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]];
NSString* underscoredModelName = [[[self class] modelName] underscore];
for (NSString* elementName in [elementsAndProperties allKeys]) {
id value = [elementsAndProperties valueForKey:elementName];
NSString* attributeName = [elementName stringByReplacingOccurrencesOfString:@"-" withString:@"_"];
if (![attributeName isEqualToString:@"id"]) {
NSString* keyName = [NSString stringWithFormat:@"%@[%@]", underscoredModelName, attributeName];
[resourceParams setValue:value forKey:keyName];
}
}
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];
if (nil != error) {
NSLog(@"Error saving persistent store: %@", error);
}
return error;
}
// TODO: Delete on the server also? See above.
- (void)destroy {
[[self managedObjectContext] deleteObject:self];
}
- (void)setAttributesFromXML:(Element*)XML {
[[[OTRestModelManager manager] mapper] setAttributes:self fromXML:XML];
}
@end