3

我对 Ember 数据和 Mongodb 嵌入对象有疑问。这是我的模型:

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 /app/api/v1/contact/4f86c4774ab63c2417000001/) 这是我得到的:

{
    "additional_names": null,
    "addresses": [],
    "birthday": null,
    "civility": null,
    "emails": [
        {
            "email": "alexandre@test.com",
            "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,而只在根文档上设置。

这样 ember-data 会看到“电子邮件”对象没有 id,然后它会尝试通过 API 获取完整的对象。例如:GET /app/api/v1/email/set// 404(未找到)

为了确定这是一个赖特问题,我尝试返回带有假 ID 字段的 Mongodb 子文档。喜欢:(请参阅电子邮件对象的区别)

{
    "additional_names": null,
    "addresses": [],
    "birthday": null,
    "civility": null,
    "emails": [
        {
            "id": 431,
            "email": "alexandre@test.com",
            "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
}

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

4

1 回答 1

3

我已经开始尝试一种解决方法。我只在只读的基础上使用没有 ID 的嵌入对象,所以我没有测试保存、创建和正确的模型状态管理(isDirty 等)......但到目前为止,这已经解决了我的类似问题。

不幸的是,我需要修改 ember-data 源。请参阅的 ember-data 分支。

我的更改范围涉及修改hasAssociation(). DS.hasMany我所做的是在访问关联的计算属性第一次返回时注入假 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,但 ember-data 首先获取对象的所有 ID,然后获取对象本身的方式,即使对于嵌入式关联也是如此,这意味着需要一些像这样的混乱解决方案。

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

干杯,凯文

于 2012-08-07T02:45:36.793 回答