RestKit を使用する iPhone アプリに取り組んでいます。サーバーへのオブジェクトの POST に問題があります。投稿を保存すると、TableView フィードには表示されますが、サーバーには保存されません。xcode で次のようなエラーが表示されます。
Object request failed: Underlying HTTP request operation failed with error: Error Domain=org.restkit.RestKit.ErrorDomain Code=-1011 "Expected status code in (200-299), got 500"
さらに、コンソールで次のように表示されます。
AFNetworkingOperationFailingURLRequestErrorKey=<NSMutableURLRequest https://stormy.herokuapp.com/posts>, NSErrorFailingURLKey=https://stormy.herokuapp.com/posts, NSLocalizedDescription=Expected status code in (200-299), got 500, AFNetworkingOperationFailingURLResponseErrorKey=<NSHTTPURLResponse: 0x841d450>}
私の NSManagedObject MPost は次のようになります
@interface MPost : NSManagedObject
@property (nonatomic, retain) NSNumber * postID;
@property (nonatomic, retain) id jsonURL;
@property (nonatomic, retain) id htmlURL;
@property (nonatomic, retain) NSString * bodyText;
@property (nonatomic, retain) NSDate * createdAt;
@property (nonatomic, retain) MUser *user;
これは私のAppDelegateです
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSError *error = nil;
NSURL *modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"Markofresh" ofType:@"momd"]];
// NOTE: Due to an iOS 5 bug, the managed object model returned is immutable.
NSManagedObjectModel *managedObjectModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL] mutableCopy];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
// Initialize the Core Data stack
[managedObjectStore createPersistentStoreCoordinator];
NSPersistentStore __unused *persistentStore = [managedObjectStore addInMemoryPersistentStore:&error];
NSAssert(persistentStore, @"Failed to add persistent store: %@", error);
[managedObjectStore createManagedObjectContexts];
// Configure a managed object cache to ensure we do not create duplicate objects
managedObjectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext];
// Set the default store shared instance
[RKManagedObjectStore setDefaultStore:managedObjectStore];
// Configure the object manager
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"https://stormy.herokuapp.com"]];
objectManager.managedObjectStore = managedObjectStore;
[RKObjectManager setSharedManager:objectManager];
RKEntityMapping *entityMapping = [RKEntityMapping mappingForEntityForName:@"Post" inManagedObjectStore:managedObjectStore];
[entityMapping addAttributeMappingsFromDictionary:@{
@"id": @"postID",
@"url": @"jsonURL",
@"body": @"bodyText",
@"public": @"public",
@"created_at": @"createdAt"}];
entityMapping.identificationAttributes = @[ @"postID" ];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:entityMapping pathPattern:@"/posts" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:responseDescriptor];
RKRequestDescriptor * requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[entityMapping inverseMapping] objectClass:[MPost class] rootKeyPath:@"/posts"];
[objectManager addRequestDescriptor:requestDescriptor];
RKObjectMapping *responseMapping = [RKObjectMapping mappingForClass:[MPost class]];
[responseMapping addAttributeMappingsFromArray:@[@"bodyText", @"postID", @"createdAt"]];
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful); // Anything in 2xx
RKResponseDescriptor *postDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:responseMapping pathPattern:@"/posts" keyPath:@"/posts" statusCodes:statusCodes];
RKObjectMapping *requestMapping = [RKObjectMapping requestMapping]; // objectClass == NSMutableDictionary
[requestMapping addAttributeMappingsFromArray:@[@"bodyText", @"postID", @"createdAt"]];
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:requestMapping objectClass:[MPost class] rootKeyPath:@"posts"];
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"https://stormy.herokuapp.com"]];
[manager addRequestDescriptor:requestDescriptor];
[manager addResponseDescriptor:postDescriptor];
[objectManager addRequestDescriptor:requestDescriptor];
// Override point for customization after application launch.
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
MasterViewController *controller = (MasterViewController *)navigationController.topViewController;
controller.managedObjectContext = managedObjectStore.mainQueueManagedObjectContext;
return YES;
}
NewPost クラスの savePost メソッドは次のとおりです。
-(void)saveChanges {
RKManagedObjectStore *objectStore = [[RKObjectManager sharedManager] managedObjectStore];
MPost *post = [NSEntityDescription insertNewObjectForEntityForName:@"Post" inManagedObjectContext:objectStore.mainQueueManagedObjectContext];
[post setBodyText:@"This is the body."];
[[RKObjectManager sharedManager] postObject:post path:@"/posts" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(@"Success saving post");
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(@"Failure saving post: %@", error.localizedDescription);
}];
何か案は?
Railsアプリモデルにuser_id presenece:true parmamがありますが、xcodeアプリにユーザーがいないため、失敗していますか? それとも、xcode と rails のクラス宣言の不一致ですか?
編集成功した投稿からのサーバーログは次のとおりです
2013-06-18T17:46:41.822383+00:00 app[web.1]: Started POST "/posts" for 76.171.148.52 at 2013-06-18 17:46:41 +0000
2013-06-18T17:46:41.825320+00:00 app[web.1]: Parameters: {"utf8"=>"✓", "authenticity_token"=>"8VvNPJXOuTNvS4ewEmXAvYHkcyKAnktHrpfQhRgHFy4=", "post"=>{"body"=>"shyea"}, "commit"=>"Create Post"}
2013-06-18T17:46:41.825160+00:00 app[web.1]: Processing by PostsController#create as HTML
2013-06-18T17:46:41.943001+00:00 app[web.1]: Redirected to https://stormy-river-3647.herokuapp.com/posts/4
2013-06-18T17:46:41.943001+00:00 app[web.1]: Completed 302 Found in 116ms (ActiveRecord: 7.8ms)
2013-06-18T17:46:42.410628+00:00 heroku[router]: at=info method=GET path=/posts/4 host=stormy-river-3647.herokuapp.com fwd="76.171.148.52" dyno=web.1 connect=1ms service=66ms status=200 bytes=2040
2013-06-18T17:46:42.353386+00:00 app[web.1]: Started GET "/posts/4" for 76.171.148.52 at 2013-06-18 17:46:42 +0000
2013-06-18T17:46:42.357829+00:00 app[web.1]: Processing by PostsController#show as HTML
2013-06-18T17:46:42.366143+00:00 app[web.1]: Parameters: {"id"=>"4"}
2013-06-18T17:46:42.381884+00:00 app[web.1]: Rendered posts/show.html.erb within layouts/application (4.0ms)
2013-06-18T17:46:41.943499+00:00 heroku[router]: at=info method=POST path=/posts host=stormy.herokuapp.com fwd="76.171.148.52" dyno=web.1 connect=1ms service=142ms status=302 bytes=113
これは、投稿が失敗した後のサーバー ログにあります。
2013-06-18T22:55:01.571679+00:00 app[web.1]: Started POST "/posts" for 76.171.148.52 at 2013-06-18 22:55:01 +0000
2013-06-18T22:55:01.579270+00:00 app[web.1]: WARNING: Can't verify CSRF token authenticity
2013-06-18T22:55:01.579270+00:00 app[web.1]: Processing by PostsController#create as JSON
2013-06-18T22:55:01.578909+00:00 app[web.1]: app/controllers/posts_controller.rb:39:in `create'
2013-06-18T22:55:01.578909+00:00 app[web.1]: NoMethodError (undefined method `posts' for nil:NilClass):
2013-06-18T22:55:01.579270+00:00 app[web.1]: Parameters: {"post"=>{"body"=>"This is the body."}}
2013-06-18T22:55:01.579270+00:00 app[web.1]: Completed 500 Internal Server Error in 1ms
問題はレール側ですか?posts_controllerで?