RestKit 0.9.3 connectRelationship:withObjectForPrimaryKeyAttribute:

发布于 2024-12-03 17:09:16 字数 2930 浏览 1 评论 0原文

我正在尝试使用新 RestKit 0.9.3 中的示例 RKCatalog。 在 RKRelationshipMappingExample 中,创建者忘记在任务和用户之间添加连接代码,但即使添加后也无法正常工作。

{"project": {
    "id": 123,
    "name": "Produce RestKit Sample Code",
    "description": "We need more sample code!",
    "user": {
        "id": 1,
        "name": "Blake Watters",
        "email": "[email protected]"
    },
    "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 将任务连接到用户。

I am trying to use example RKCatalog from new RestKit 0.9.3.
In RKRelationshipMappingExample creators have forgotten to add connection code between Task and User, but even after adding it doesn't work correctly.

{"project": {
    "id": 123,
    "name": "Produce RestKit Sample Code",
    "description": "We need more sample code!",
    "user": {
        "id": 1,
        "name": "Blake Watters",
        "email": "[email protected]"
    },
    "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;
}

Am i doing everything alright? -- it doesn't connect task to user by user's ID.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

洛阳烟雨空心柳 2024-12-10 17:09:16

更新:我应该更仔细地阅读 Blake 的链接帖子 - - 它会让我更快地找到开发分支。

底线:一对多映射问题(此处在 User 对象的 tasks 的逆水合上下文中讨论)已损坏在 0.9.3 中。截至 2012 年 3 月 8 日,开发分支的拉取确认该问题已解决——Blake 在问题 #284 中解决了该问题。您仍然需要添加示例中未包含的 connectRelationship:withObjectForPrimaryKeyAttribute: 逻辑。


@Evan,感谢有关 RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace) 的提示——它对于分析实际发生​​的情况很有帮助。

我仍然处于 RestKit 的“寻找自己的出路”阶段,所以 YMMV。然而,根据 Blake 的这篇文章,它实际上看起来就像你两者都需要一样——这是我能让这个例子发挥作用的唯一方法。但是,对相关对象上主键的引用是使用其本地 [即任务的 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 天前从 master 进行的拉取运行的。

UPDATED: I should have read Blake's linked post more carefully -- it would have pointed me to the development branch more quickly.

BOTTOM LINE: the one-to-many mapping issue (discussed here in the context of the inverse hydration of the User object's tasks) is broken in 0.9.3. A pull of the development branch as of 3/8/2012 confirms that the problem is fixed there -- Blake addressed it in issue #284. You do still need to add the connectRelationship:withObjectForPrimaryKeyAttribute: logic that the example does not contain.


@Evan, thanks for the tip on RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace) -- it's been helpful for profiling what's actually happening.

I'm still very much in the "finding my way" stage of RestKit, so YMMV. However, according to this post by Blake, it actually looks like you need both -- it's the only way I could get the example to work. However, the reference to the primary key on the related object is referred to using it's local [i.e., Task's ivar] attribute:

        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"]; 

This was run against a pull from master of about 3 days ago.

暗恋未遂 2024-12-10 17:09:16

用户->任务映射在 userMapping 上设置,使用行 [userMapping mapRelationship:@"tasks" withMapping:taskMapping];。我想你是说逆矩阵没有创建?

如果这就是问题所在,我想您会发现 此提交 解决了该问题我自己还没试过。 (您可以在此时拉动树,或者更好的是拉动当前的主分支)。

除此之外,您的行 [taskMapping connectRelationship:@"signedUser" withObjectForPrimaryKeyAttribute:@"signedUserID"]; 存在问题,它正在搜索主键属性为“assignedUserID”的对象,但是查看其他映射,不存在这样的对象。请注意,在 userMapping 上,主键由 [userMapping setPrimaryKeyAttribute:@"userID"]; 定义,

您可能需要 [taskMapping connectRelationship:@"signedUser" withObjectForPrimaryKeyAttribute:@"userID"];,甚至更好 [taskMapping mapRelationship:@"signedUser" withMapping:userMapping];

(并且随着提交我链接,我什至不确定是否有必要添加任何内容来获得逆 - 您可以尝试两者并查看。)

如果仍然存在问题,您可以使用 RKLogConfigureByName("RestKit" 打开 ObjectMapper 的日志/ObjectMapping", RKLogLevelTrace);

The user -> task mapping is set up on userMapping, with the line [userMapping mapRelationship:@"tasks" withMapping:taskMapping];. I assume you're saying that the inverse was not created?

If that's the issue, I think you'll find that this commit fixes the issue, though I haven't tried it myself yet. (You could pull the tree at that point or, better, pull the current master branch).

That aside, you have a problem with the line [taskMapping connectRelationship:@"assignedUser" withObjectForPrimaryKeyAttribute:@"assignedUserID"]; It's searching for a an object with a primary key attribute of "assignedUserID", but looking at the other mappings, no such object exists. Note that on userMapping, the primary key is defined by [userMapping setPrimaryKeyAttribute:@"userID"];

You probably want [taskMapping connectRelationship:@"assignedUser" withObjectForPrimaryKeyAttribute:@"userID"];, or even better [taskMapping mapRelationship:@"assignedUser" withMapping:userMapping];

(And with the commit I linked, I'm not even sure if it's necessary to add anything at all to get the inverse - you can try both and see.)

If there are still problems you can turn on logs for the ObjectMapper with RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace);

剑心龙吟 2024-12-10 17:09:16

我已经把这段代码弄乱了近一个半小时,终于让它工作了。我已采取的步骤:
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];
}

I've been messing with this code for close to an hour and a half, and finally got it to work. Steps that I've taken:
1) Rearrange the creation of relationships like below
2) Unchecked the "optional" checkmark for the RKRelationshipMappingExample.xcdatamodel > task.assignedUser relationship. I noticed it was both "optional" and minimum 1, maximum 1. I deleted the app after this change and reinstalled it. Now the users are added to tasks and tasks to users!

- (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];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文