Ember Data - 多态关系

时间:2015-02-14 16:41:02

标签: ember.js ember-data

我只是偶然发现了Ember Data Polymorphic Relationships。我认为它们对我正在做的事情很有用。这是我的主要模特。该模型定义了与异步和多态的主题有很多关系。

App.Source = DS.Model.extend({
    name: DS.attr('string'),
    type: DS.attr('string'),
    locationType: DS.attr('string'),
    locationSpecific: DS.attr('boolean'),
    primary: DS.attr('boolean'),
    published: DS.attr('boolean'),
    sort: DS.attr('number'),
    topics: DS.hasMany('topic', {
        async: true,
        polymorphic: true
    })
});

接下来,我们将基础类的主题设为'主题'

App.Topic = DS.Model.extend({
    name: DS.attr('string'),
    sort: DS.attr('number'),
    source: DS.belongsTo('source')
});

App.RegTopic = App.Topic.extend({
    test: DS.attr('number', {
        defaultValue: 8
    }),
    notes: DS.hasMany('notes', {
        async: true
    })
});

App.SummaryTopic = App.Topic.extend({
    number: DS.attr('number', {
        defaultValue: 9
    })
});

以下是我打电话来获取主题的方法

App.TopicsRoute = Ember.Route.extend({
     model: function() {
           return this.modelFor('source').get('topics');
     }
});

当我列出来源时,我会得到以下对象的列表

 {
         id: 1
         name: "test"
         type: "testType"
         locationType: "international"
         locationSpecific: "true"
         primary: true
         published: true
         sort: 1
         links: {
                 topics: "/topics?sourceId=1"
         }
    }

然后我的主题调用得到这样的对象

{
   id: 4
   sourceId: 1
   name: Topic 4
   type: "regTopic"
   sort: 1
}

我错过了什么吗?你能不能在'链接'中使用多态关系?对象

根据我对多态关系的理解,当我调用/ topics?sourceId = 1时,它应该基本上在一个调用中加载2个不同的主题,这样我就可以在同一页面上显示regTopic和summaryTopic但是分开列出并将它们保存为单独的对象?

这是一个更新的jsbin,似乎接近工作。 http://emberjs.jsbin.com/medojitibo/1/edit?html,js,console,output

问题我看到它在我的控制器中,主题都是列表中的App.Topic。没有App.RegTopic或App.SummaryTopic

2 个答案:

答案 0 :(得分:0)

links元素看起来像JSON-API,其中有addon。我必须在我的fork中对多态性进行修改。修改后端以支持Ember Data指定的API可能更容易。

答案 1 :(得分:0)

我不建议使用Ember Data多态性,除非你真的知道自己在做什么,并且确信自己能够满足你的需求。目前,它专为相当有限的用例而设计。如果您有兴趣,可以跟踪有关该主题的一些讨论和建议。

您显然相信,或者API认为,links对象的JSON中source属性的格式是包含单个(?)topics属性的对象,给出用于检索多态主题的API端点。这根本不是它的工作方式。

返回的JSON中links属性的正确语法是{id, type}个连音符数组:

{
    id: 1
    name: "test"
    type: "testType"
    ...
    links: [
        { id: 'topic1', type: 'regTopic'},
        { id: 'topic2', type: 'summaryTopic' }
    ]
}

如上所示,关联数据的格式是一个id / type对象的数组,而不仅仅是一个id数组。这是Ember Data多态性工作所必需的。如果你不能安排你的后端产生这种格式,那么你最终会在适配器和序列化器中修补和破解许多方法,并在一天结束时构建你自己的多态性版本,可能不是你想要开展的一项努力。

如果没有这种特殊形式的JSON用于关联属性,Ember Data不知道要寻找什么类型的对象。有了它,Ember Data将为此topic数组中的每个条目创建topics的正确实例类型,并基本上调用find('reg-topic', 'topic1')find('summary-topic', 'topic2')来获取其数据。这意味着您还需要为每个主题子类型使用单独的API端点。 (如果主题是嵌入的,那​​么事情会有所不同,我不会在这里找到另一种选择。)

到目前为止,这很好,也许。但是一旦你开始做更复杂的事情,这就会开始迅速崩溃。假设您想要获取/检索具有特定ID的主题。有人可能认为,因为"主题是多态的",你可以做this.store.get('topic', id)。但你不能。商店将RegTopicSummaryTopic分隔在不同的位置,并且不会将其与Topic相关联。如果您要求提供“主题”,则不知道在商店中已有的实例中查看不同(子)模型。因此,您必须事先知道类型是什么,并要求商店记录该特定类型,这种类型会破坏多态性的整个目的。如果您只是调用topics端点,Ember Data将为Topic创建一个新的模型实例 - 它不知道它应该检查返回的JSON的type字段管理将其转换为什么子类型。

关键是这里的主题是多态。在Ember Data中,多态性不在模型级别;它处于关联级别。换句话说,这里的多态是什么,不是topic模型本身;它是links模型上source属性中的关联。换句话说,Ember Data不知道模型本身是多态的;它只知道特定的关联(hasManybelongsTo)可以保存多态值。有关使Ember Data真正支持多态模型可能需要的一些见解,尽管情况略有不同,请查看https://github.com/Bestra/ember-data-sti-guide

要在评论中回答您的问题,不,Ember Data多态性不是您想要的最佳方式。不要冒险进入这些未知的水域。我采用了“穷人的多态性"”的策略,其中Topic模型具有类型字段,并且可能或可能具有一些不同的属性,具体取决于类型。然后,您可以根据心脏的内容对类型进行排序,分组和过滤。