RestKit 0.9.3 connectRelationhip: withObjectForPrimaryKeyAttribute: - PullRequest
2 голосов
/ 07 сентября 2011

Я пытаюсь использовать пример RKCatalog из нового RestKit 0.9.3. В RKRelationshipMappingExample создатели забыли добавить код соединения между Задачей и Пользователем, но даже после добавления он работает некорректно.

{"project": {
    "id": 123,
    "name": "Produce RestKit Sample Code",
    "description": "We need more sample code!",
    "user": {
        "id": 1,
        "name": "Blake Watters",
        "email": "blake@twotoasters.com"
    },
    "tasks": [
        {"id": 1, "name": "Identify samples to write", "assigned_user_id": 1},
        {"id": 2, "name": "Write the code", "assigned_user_id": 1},
        {"id": 3, "name": "Push to Github", "assigned_user_id": 1},
        {"id": 4, "name": "Update the mailing list", "assigned_user_id": 1}
    ]
}}

[taskMapping connectRelationship:@"assignedUser" withObjectForPrimaryKeyAttribute:@"assignedUserID"];

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        RKObjectManager* objectManager = [RKObjectManager objectManagerWithBaseURL:gRKCatalogBaseURL];
        objectManager.objectStore = [RKManagedObjectStore objectStoreWithStoreFilename:@"RKRelationshipMappingExample.sqlite"];

        RKManagedObjectMapping* taskMapping = [RKManagedObjectMapping mappingForClass:[Task class]];
        [taskMapping mapKeyPath:@"id" toAttribute:@"taskID"];
        [taskMapping setPrimaryKeyAttribute:@"taskID"];
        [taskMapping mapKeyPath:@"name" toAttribute:@"name"];
        [taskMapping mapKeyPath:@"assigned_user_id" toAttribute:@"assignedUserID"];
        [taskMapping connectRelationship:@"assignedUser" withObjectForPrimaryKeyAttribute:@"assignedUserID"];
        [objectManager.mappingProvider setMapping:taskMapping forKeyPath:@"task"];

        RKManagedObjectMapping* userMapping = [RKManagedObjectMapping mappingForClass:[User class]];
        [userMapping mapAttributes:@"name", @"email", nil];
        [userMapping mapKeyPath:@"id" toAttribute:@"userID"];
        [userMapping setPrimaryKeyAttribute:@"userID"];
        [userMapping mapRelationship:@"tasks" withMapping:taskMapping];
        [objectManager.mappingProvider setMapping:userMapping forKeyPath:@"user"];

        // NOTE - Project is not backed by Core Data
        RKObjectMapping* projectMapping = [RKObjectMapping mappingForClass:[Project class]];
        [projectMapping mapKeyPath:@"id" toAttribute:@"projectID"];
        [projectMapping mapAttributes:@"name", @"description", nil];
        [projectMapping mapRelationship:@"user" withMapping:userMapping];
        [projectMapping mapRelationship:@"tasks" withMapping:taskMapping];
        [objectManager.mappingProvider setMapping:projectMapping forKeyPath:@"project"];
    }

    return self;
}

Я все делаю хорошо? - не связывает задачу с пользователем по ID пользователя.

Ответы [ 3 ]

2 голосов
/ 22 февраля 2012

ОБНОВЛЕНО: я должен был прочитать пост Блейка, связанный с ним более внимательно - он бы быстрее указывал мне на ветку разработки.

BOTTOM LINE: отображение один-ко-многимпроблема (обсуждаемая здесь в контексте обратной гидратации User объекта tasks) - нарушена в 0.9.3.Поток ветки разработки от 08.03.2012 подтверждает, что проблема там устранена - Блейк обратился к ней в выпуске № 284.* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Evan, спасибо за подсказку по RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace), спасибо за подсказку по *1015*Профилирование того, что на самом деле происходит.

Я все еще нахожусь на стадии «найти свой путь» RestKit, так что YMMV.Однако, согласно этой записи Блейка , на самом деле похоже, что вам нужно и то и другое - это единственный способ, которым я смог заставить пример работать.Однако ссылка на первичный ключ в связанном объекте ссылается на его локальный атрибут [т.е., ivar] Задачи:

        RKManagedObjectMapping* taskMapping = [RKManagedObjectMapping mappingForClass:[Task class]];
        [taskMapping mapKeyPath:@"id" toAttribute:@"taskID"];
        [taskMapping mapKeyPath:@"name" toAttribute:@"name"];
        [taskMapping mapKeyPath:@"assigned_user_id" toAttribute:@"assignedUserID"];
        taskMapping.primaryKeyAttribute = @"taskID";

        RKManagedObjectMapping* userMapping = [RKManagedObjectMapping mappingForClass:[User class]];
        [userMapping mapAttributes:@"name", @"email", nil];
        [userMapping mapKeyPath:@"id" toAttribute:@"userID"];
        [userMapping mapRelationship:@"tasks" withMapping:taskMapping];
        userMapping.primaryKeyAttribute = @"userID";
        [objectManager.mappingProvider setMapping:userMapping forKeyPath:@"user"];

        [taskMapping mapRelationship:@"assignedUser" withMapping:userMapping];
        [taskMapping connectRelationship:@"assignedUser" withObjectForPrimaryKeyAttribute:@"assignedUserID"];
        [objectManager.mappingProvider setMapping:taskMapping forKeyPath:@"task"]; 

Это было выполнено для извлечения из мастера около 3 дней назад.

1 голос
/ 06 марта 2012

Я возился с этим кодом почти полтора часа и, наконец, получил его на работу. Шаги, которые я предпринял: 1) Переставить создание отношений как ниже 2) Снял флажок «необязательно» для отношения RKRelationshipMappingExample.xcdatamodel> task.assignedUser. Я заметил, что это было «необязательно» и минимум 1, максимум 1. После удаления приложения я удалил приложение и переустановил его , Теперь пользователи добавляются в задачи и задачи для пользователей!

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        RKObjectManager* objectManager = [RKObjectManager objectManagerWithBaseURL:gRKCatalogBaseURL];
        objectManager.objectStore = [RKManagedObjectStore objectStoreWithStoreFilename:@"RKRelationshipMappingExample.sqlite"];


        RKManagedObjectMapping* taskMapping = [RKManagedObjectMapping mappingForClass:[Task class]];
        [taskMapping mapKeyPath:@"id" toAttribute:@"taskID"];
        [taskMapping mapKeyPath:@"name" toAttribute:@"name"];
        [taskMapping mapKeyPath:@"assigned_user_id" toAttribute:@"assignedUserID"];
        taskMapping.primaryKeyAttribute = @"taskID";

        RKManagedObjectMapping* userMapping = [RKManagedObjectMapping mappingForClass:[User class]];
        [userMapping mapAttributes:@"name", @"email", nil];
        [userMapping mapKeyPath:@"id" toAttribute:@"userID"];

        userMapping.primaryKeyAttribute = @"userID";
        [objectManager.mappingProvider setMapping:userMapping forKeyPath:@"user"];
        [objectManager.mappingProvider setMapping:taskMapping forKeyPath:@"task"];

        [userMapping mapRelationship:@"tasks" withMapping:taskMapping];        
        [taskMapping mapRelationship:@"assignedUser" withMapping:userMapping];

        [taskMapping connectRelationship:@"assignedUser" withObjectForPrimaryKeyAttribute:@"assignedUserID"];


        // NOTE - Project is not backed by Core Data
        RKObjectMapping* projectMapping = [RKObjectMapping mappingForClass:[Project class]];
        [projectMapping mapKeyPath:@"id" toAttribute:@"projectID"];
        [projectMapping mapAttributes:@"name", @"description", nil];
        [projectMapping mapRelationship:@"user" withMapping:userMapping];
        [projectMapping mapRelationship:@"tasks" withMapping:taskMapping];
        [objectManager.mappingProvider setMapping:projectMapping forKeyPath:@"project"];



    }

    return self;
}

//to see NSLog messages, change the LOGGER_DEBUG to 2 (in LoggerClient.m) like this:
#define LOGGER_DEBUG 2
#ifdef NSLog
    #undef NSLog
#endif



//test method to make sure all relationships are created.
- (void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects {
    _objects = [objects retain];

    for(Project* managedObject in objects)
    {   NSLog(@" project user: %@", [managedObject.user description]);
        NSLog(@"###### user tasks count: %i",[managedObject.user.tasks  count]);
        for(Task* task in managedObject.user.tasks)
        {
            NSLog(@"+++++managedObject.user.tasks: %@", [task description]);
        }

        for(Task* task in managedObject.tasks)
        {
            NSLog(@"*****task: %@", [task description]);
        }

    }
    [self.tableView reloadData];
}
1 голос
/ 07 сентября 2011

Пользователь -> сопоставление задач настраивается на userMapping со строкой [userMapping mapRelationship:@"tasks" withMapping:taskMapping];. Я полагаю, вы говорите, что обратное не было создано?

Если это проблема, я думаю, вы обнаружите, что этот коммит устраняет проблему, хотя я сам еще не пробовал. (Вы можете потянуть дерево в этой точке или, что лучше, потянуть текущую основную ветвь).

Кроме того, у вас есть проблема со строкой [taskMapping connectRelationship:@"assignedUser" withObjectForPrimaryKeyAttribute:@"assignedUserID"]; Он ищет объект с атрибутом первичного ключа "assignUserID", но, глядя на другие сопоставления, такого объекта не существует. Обратите внимание, что в userMapping первичный ключ определяется как [userMapping setPrimaryKeyAttribute:@"userID"];

Вы, вероятно, хотите [taskMapping connectRelationship:@"assignedUser" withObjectForPrimaryKeyAttribute:@"userID"];, или даже лучше [taskMapping mapRelationship:@"assignedUser" withMapping:userMapping];

(И с коммитом, который я связал, я даже не уверен, нужно ли вообще что-либо добавлять, чтобы получить обратное - вы можете попробовать оба варианта и посмотреть.)

Если проблемы все еще есть, вы можете включить журналы для ObjectMapper с помощью RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace);

...