Как поместить объект в рельсы, используя RestKit? - PullRequest
6 голосов
/ 07 декабря 2011

Я пытаюсь заставить волшебство случиться с RestKit и Rails. Я использую Rails 3.1.1 и RestKit 0.9.3 (не основная ветка). Я использую Core Data в своем приложении для iOS, поэтому я пытаюсь настроить приложение на использование как можно большего количества магии RestKit для взаимодействия с приложением rails.

Однако у меня возникла проблема при попытке размещения нового объекта на моем сервере. Я успешно получил объекты вниз. Вот мой код для этого:

RKObjectManager* manager = [RKObjectManager objectManagerWithBaseURL:@"http://IP_ADDRESS"];
manager.objectStore = [RKManagedObjectStore objectStoreWithStoreFilename:@"magikarp.sqlite"];
manager.client.requestQueue.showsNetworkActivityIndicatorWhenBusy = YES;
manager.acceptMIMEType = RKMIMETypeJSON; 
manager.serializationMIMEType = RKMIMETypeJSON; 

///
/// Setup Routing
///

RKObjectRouter *router = [[RKObjectRouter alloc] init];
[router routeClass:[List class] toResourcePath:@"/lists/(listID)"];
[router routeClass:[List class] toResourcePath:@"/lists" forMethod:RKRequestMethodPOST];
manager.router = router;

///
/// Setup mapping for my "List" object; a subclass of NSManagedObject
///
RKManagedObjectMapping *listMapping = [RKManagedObjectMapping mappingForClass:[List class]];
listMapping.primaryKeyAttribute = @"listID";

[listMapping mapAttributes:@"title", nil];
[listMapping mapKeyPath:@"id" toAttribute:@"listID"];
[manager.mappingProvider setMapping:listMapping forKeyPath:@"list"];

Мне кажется, это хорошо работает. Теперь я хочу отправить вновь созданный объект обратно на сервер.

- (void)createList:(NSString *)listName {
    List *newList = [List object];
    newList.title = listName;
    [[RKObjectManager sharedManager] postObject:newList delegate:self]; 
}

Я вызываю этот метод с именем, которое я хочу получить в новом списке. Этот метод вызывается, но я получаю эту ошибку:

2011-12-06 19:24:17.822 Magikarp[13921:14c1b] W restkit.object_mapping:RKObjectMapper.m:74 Adding mapping error: Could not find an object mapping for keyPath: ''
2011-12-06 19:24:17.823 Magikarp[13921:14c1b] E restkit.network:RKObjectLoader.m:190 Encountered errors during mapping: Could not find an object mapping for keyPath: ''
2011-12-06 19:24:17.823 Magikarp[13921:14c1b] Hit error: Error Domain=org.restkit.RestKit.ErrorDomain Code=1001 "Could not find an object mapping for keyPath: ''" UserInfo=0x6bb9da0 {=RKObjectMapperKeyPath, NSLocalizedDescription=Could not find an object mapping for keyPath: ''}

Я попытался сделать сопоставление следующим образом:

RKObjectMapping *listSerializationMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
[listSerializationMapping mapKeyPath:@"title" toAttribute:@"title"];
[listSerializationMapping mapKeyPath:@"ListID" toAttribute:@"id"];
[manager.mappingProvider setSerializationMapping:listSerializationMapping forClass:[List class]];

(Это дает вышеуказанную ошибку). Я знаю, что есть довольно простой способ сделать это, но ни в одном из примеров нет этого кода, и вся документация кажется устаревшей ... Вам также нужно отправлять информацию в качестве параметров POST? Буду признателен за помощь, спасибо!

Обновление
Это ответ сервера - он работает, но кажется, что параметры немного испорчены? (Название, которое я вставил: «Сделано из iPhone 2!»)

Started POST "/lists" for 129.21.86.32 at 2011-12-07 09:34:43 -0500
  Processing by ListsController#create as JSON
  Parameters: {"id"=>0, "title"=>"Made from the iPhone 2!", "list"=>{"id"=>0, "title"=>"Made from the iPhone 2!"}}
WARNING: Can't verify CSRF token authenticity
WARNING: Can't mass-assign protected attributes: id
   (0.3ms)  BEGIN
  SQL (0.9ms)  INSERT INTO "lists" ("created_at", "title", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["created_at", Wed, 07 Dec 2011 14:34:43 UTC +00:00], ["title", "Made from the iPhone 2!"], ["updated_at", Wed, 07 Dec 2011 14:34:43 UTC +00:00]]
   (16.4ms)  COMMIT
Completed 201 Created in 77ms (Views: 1.8ms | ActiveRecord: 21.9ms)

Ответы [ 2 ]

8 голосов
/ 07 декабря 2011

Я думаю, что селектора inverseMapping должно быть достаточно, чтобы выполнить преобразование сериализации

RKManagedObjectMapping *listMapping = [RKManagedObjectMapping mappingForClass:[List class]];
listMapping.primaryKeyAttribute = @"listID";

[listMapping mapAttributes:@"title", nil];
[listMapping mapKeyPath:@"id" toAttribute:@"listID"];
[manager.mappingProvider setMapping:listMapping forKeyPath:@"list"];
//this should be enough
[manager.mappingProvider setSerializationMapping:[listMapping inverseMapping] forClass:[List class]];

Редактировать:

в соответствии с нашей беседой в чате, предупреждения RestKit были вызваныДело в том, что в ответе сервера не было корневого ключа KeyPath (возвращается как голый массив).Чтобы решить эту проблему, мы должны указать RestKit использовать конкретное сопоставление для сопоставления ответа:

mapping = [[[RKObjectManager sharedManager] mappingProvider] mappingForKeyPath:@"list"];
[[RKObjectManager sharedManager] postObject:newList mapResponseWith:mapping delegate:self];
2 голосов
/ 17 февраля 2012

Это из документации по RestKit.Существует удобный метод, который устанавливает как сопоставление, так и сопоставление сериализации

[[RKObjectManager sharedManager].mappingProvider registerMapping:mapping withRootKeyPath:@"person"];

Это вызовет setMapping: forKeyPath: для вас, затем создаст сопоставление сериализации и также установит корневой keyPath.

...