2012-07-31 41 views
3

我有关于Ember数据和Mongodb嵌入对象的问题。这里是我的模型:emberdata和mongodb嵌入对象ID undefined

App.Contact = App.Entity.extend({ 
    name    : DS.attr('string'), 
    firstname  : DS.attr('string'), 
    additional_names : DS.attr('string'), 
    civility   : DS.attr('string'), 
    birthday   : DS.attr('date'), 
    organization  : DS.belongsTo('App.Organization'), 
    role    : DS.attr('string'), 
    photo_source  : DS.attr('string'), 
    photo_uri  : DS.attr('string'), 
    gravatar_mail : DS.attr('string'), 
    addresses  : DS.hasMany('App.Address', { embedded: true }), 
    emails   : DS.hasMany('App.Email', { embedded: true }), 
    phones   : DS.hasMany('App.Phone', { embedded: true }) 
}); 

现在我获取通过API联系人:(GET /应用/ API/V1 /联系人/ 4f86c4774ab63c2417000001 /)这里就是我得到:

{ 
    "additional_names": null, 
    "addresses": [], 
    "birthday": null, 
    "civility": null, 
    "emails": [ 
     { 
      "email": "[email protected]", 
      "label": null, 
      "resource_uri": "/app/api/v1/contact/4f86c4774ab63c2417000001/emails/0/", 
      "type": "HOME" 
     } 
    ], 
    "firstname": "Alexandre", 
    "gravatar_mail": null, 
    "groups": [], 
    "id": "4f86c4774ab63c2417000001", 
    "name": "Simoui", 
    "organization": null, 
    "phones": [], 
    "photo_source": null, 
    "photo_uri": "/static/img/nophoto.png", 
    "resource_uri": "/app/api/v1/contact/4f86c4774ab63c2417000001/", 
    "role": null 
} 

我的“根“对象有一个ID,但嵌入对象”电子邮件“没有。因为在mongodb中,id不是在子文档上设置的,而是仅在根文档上设置的。

这种方式烬数据看到“电子邮件”对象没有ID,然后它试图通过API获取完整的对象。例如:GET/app/api/v1/email/set // 404(NOT FOUND)

为了确保这是wright问题,我尝试用伪ID字段返回Mongodb子文档。喜欢:(看邮件对象的差异)

{ 
    "additional_names": null, 
    "addresses": [], 
    "birthday": null, 
    "civility": null, 
    "emails": [ 
     { 
      "id": 431, 
      "email": "[email protected]", 
      "label": null, 
      "resource_uri": "/app/api/v1/contact/4f86c4774ab63c2417000001/emails/0/", 
      "type": "HOME" 
     } 
    ], 
    "firstname": "Alexandre", 
    "gravatar_mail": null, 
    "groups": [], 
    "id": "4f86c4774ab63c2417000001", 
    "name": "Simoui", 
    "organization": null, 
    "phones": [], 
    "photo_source": null, 
    "photo_uri": "/static/img/nophoto.png", 
    "resource_uri": "/app/api/v1/contact/4f86c4774ab63c2417000001/", 
    "role": null 
} 

然后我没有问题一切都很好。所以我的问题是:有没有办法解决它?

+0

如果你已经解决了这个,你介意张贴你如何去了解它。 – brg 2012-08-17 11:52:33

+0

你有没有得到这个工作? – albertjan 2013-01-15 09:46:22

+4

查看最新版本的ember-data,发生了很多变化。 Ember-data现在支持没有ID的嵌入记录。 – ThomasDurin 2013-01-15 12:47:51

回答

3

我已经开始尝试一种解决方法。我只使用没有ID的嵌入式对象,因此我没有测试过保存,创建和适当的模型状态管理(isDirty等)......但是到目前为止,这已经解决了我的类似问题。

不幸的是我需要修改的烬数据源。请参阅ember-data的my fork

我改变的程度涉及修改DS.hasManyhasAssociation()函数。我所做的是在访问关联的计算属性第一次返回时注入伪ID。我在闭包中保存了一个客户端ID计数器injectedIdCounter,该闭包定义了hasAssociation()以及一个获取ID并更新计数器的函数。然后我定义一个新选项trueEmbedded这是一个没有ID的嵌入式子文档。每次在关联上调用get()时,都会检查元素的ID,如果ID不存在,则注入元素。如果添加了ID,则需要调用set(),以便修改的关联存储在父对象上。至少这解决了我的问题。这是我的代码。

var injectedIdCounter = 1; 
var getInjectedId = function() { 
    return injectedIdCounter++; 
}; 

var hasAssociation = function(type, options) { 
    options = options || {}; 

    var embedded = options.embedded, 
     findRecord = embedded ? embeddedFindRecord : referencedFindRecord; 

    var meta = { type: type, isAssociation: true, options: options, kind: 'hasMany' }; 

    return Ember.computed(function(key, value) { 
    var data = get(this, 'data'), 
     store = get(this, 'store'), 
     ids, id, association; 

    if (typeof type === 'string') { 
     type = get(this, type, false) || get(window, type); 
    } 

    key = options.key || get(this, 'namingConvention').keyToJSONKey(key); 
    if (options.trueEmbedded) { 
     association = get(data, key); 
     var injectedIdCount = 0; 
     association.forEach(function(item) { 
     if (Ember.none(item.id)) { 
      item.id = getInjectedId(); 
      injectedIdCount++; 
     } 
     }); 
     if (injectedIdCount > 0) { 
     set(data, key, association); 
     } 
     ids = embeddedFindRecord(store, type, data, key); 
    } else { 
     ids = findRecord(store, type, data, key); 
    } 
    association = store.findMany(type, ids || []); 
    set(association, 'parentRecord', this); 

    return association; 
    }).property().cacheable().meta(meta); 
}; 

你会认为,嵌入文档并不需要一个ID,但灰烬方式,数据首先抓取对象的所有的ID,然后对象本身,即使是一个嵌入式的关联,意味着一些这样的混乱的解决方案是必需的。

希望这将在未来的Ember版本中得到修复。

干杯, 凯文