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 は「email」オブジェクトに ID がないことを確認し、API を介して完全なオブジェクトを取得しようとします。例: GET /app/api/v1/email/set// 404 (見つかりません)

それがライトの問題であることを確認するために、偽の ID フィールドを持つ Mongodb サブドキュメントを返そうとしました。Like : (email オブジェクトの違いを参照)

{
    "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定義するクロージャーに、クライアント側の ID カウンターを保持します。次に、ID のない埋め込みサブドキュメントであるhasAssociation()新しいオプションを定義します。trueEmbeddedアソシエーションで が呼び出されるたびget()に、要素の ID がチェックされ、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 に答える