Идентификатор встроенных объектов emberdata и mongodb не определен

У меня проблема с данными 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": "[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
}

У моего «корневого» объекта есть идентификатор, а у встроенного объекта «электронная почта» нет. Потому что в mongodb id устанавливается не для вложенных документов, а только для корневого документа.

Таким образом ember-data увидит, что объект "email" не имеет идентификатора, а затем попытается получить полный объект через API. Например: ПОЛУЧИТЬ /app/api/v1/email/set// 404 (НЕ НАЙДЕНО)

Чтобы убедиться, что это была проблема с Райтом, я попытался вернуть вложенные документы 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
}

Тогда у меня нет проблем, все в порядке. Итак, мой вопрос: есть ли способ исправить это?


person ThomasDurin    schedule 31.07.2012    source источник
comment
если вы решили это, не могли бы вы опубликовать, как вы это сделали.   -  person brg    schedule 17.08.2012
comment
Вы когда-нибудь заставляли это работать?   -  person albertjan    schedule 15.01.2013
comment
Ознакомьтесь с последней версией ember-data, в ней было много изменений. Ember-data теперь поддерживает встроенные записи без идентификатора.   -  person ThomasDurin    schedule 15.01.2013
comment
@ThomasD Как вы строите отношения между объектами (помимо самой вложенности)? stackoverflow.com/questions/15441104/   -  person RyanJM    schedule 15.03.2013


Ответы (1)


Я начал экспериментировать с обходным путем. Я использую встроенные объекты без идентификаторов только для чтения, поэтому я не тестировал сохранение, создание и правильное управление состоянием модели (isDirty и т. д.)... но пока это решило мою аналогичную проблему.

К сожалению, мне нужно было изменить источник данных ember. См. мой форк ember-data.

Мои изменения включали изменение функции hasAssociation() DS.hasMany. Что я сделал, так это внедрил поддельные идентификаторы при первом возврате вычисляемого свойства, которое обращается к ассоциации. Я держу счетчик идентификатора на стороне клиента, injectedIdCounter в замыкании, которое определяет hasAssociation(), а также функцию для получения идентификатора и обновления счетчика. Затем я определяю новую опцию, trueEmbedded, которая представляет собой встроенный вложенный документ без идентификатора. Каждый раз, когда get() вызывается для ассоциации, элементы проверяются на идентификаторы, и если идентификатор не существует, он вводится. Если идентификаторы были добавлены, то необходимо вызвать 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);
};

Вы могли бы подумать, что встроенному документу не нужен идентификатор, но способ, которым ember-data сначала извлекает все идентификаторы объектов, а затем сами объекты, даже для встроенной ассоциации, означает, что требуется какое-то запутанное решение, подобное этому.

Надеюсь, это будет исправлено в будущих версиях Ember.

Привет, Кевин

person Kevin Bullaughey    schedule 07.08.2012