9

1 対多の関係を ember データに保存するのが困難です。私は次のような関係があります。

App.ParameterSet = DS.Model
    name: DS.attr("string")
    regions: DS.hasMany("App.Region")

App.Region = DS.Model
    name: DS.attr("string")

私がこのようなことをしたとしたら:

parameterSet = App.ParameterSet.find(5)
@transaction = @get("store").transaction()
@transaction.add(parameterSet)
region1 = App.Region.find(10)
region2 = App.Region.find(11)
parameterSet.set("name", "foo")
parameterSet.get("regions").pushObject(region)
@transaction.commit()

次に、次のようなペイロードを含む PUT リクエストを確認したいと思います。

api/ParameterSets/5

{parameterSet: {name: "foo", regionIds:[10, 11]}}

しかし、代わりに私はこれを取得します:

{parameterSet: {name: "foo"}}

子から親への関係は気にしませんがparameterSet: DS.belongsTo("App.ParameterSet")、App.Region モデルに追加すると、2 つの新しい関係のリージョン URL への 2 つの PUT リクエストが取得されますが、これは本当に必要なものではありません。

これは実際には多対多の関係だと思いますが、まだサポートされているかどうかはわかりませんが、私が説明したことを達成する方法についてのアイデアはありますか? ありがとう

4

2 に答える 2

8

関係のシリアル化は、のメソッドhasManyによって処理されます。addHasMany()json_serializer.js

次の注記がソースコードに含まれています。

デフォルトのRESTセマンティクスは、埋め込まれている場合にのみ、has-many関係を追加することです。リレーションシップが最初にIDによってロードされた場合、それはパフォーマンスの最適化として行われたと想定し、has-manyへの変更は、子の所属するリレーションシップの外部キーの変更として保存する必要があります。

必要なことを実現するための1つのオプションは、関係をアダプターに埋め込む必要があることを示すことです。

App.Store = DS.Store.extend({
  adapter: DS.RESTAdapter.extend({
    serializer: DS.RESTSerializer.extend({
      init: function() {
        this._super();
        this.map('App.ParameterSet', {
          regions: { embedded: 'always' }
        });
      }
    })
  })
});

もちろん、バックエンドは、関連するリージョンのJSONをパラメーターセットのJSON内に実際に埋め込む必要があります。そのままにしておきたい場合は、addHasMany()カスタムシリアル化でオーバーライドできます。

App.Store = DS.Store.extend({
  adapter: DS.RESTAdapter.extend({
    serializer: DS.RESTSerializer.extend({
      addHasMany: function(hash, record, key, relationship) {
        // custom ...
      }
    })
  })
});
于 2013-02-28T21:16:34.747 に答える
2

ahmacleod の回答にコメントを追加することはできませんが、子レコードが変更されたときに親レコードがダーティとしてマークされていないことに気付いたことを除いて、それは適切です。質問の例では、名前も親レコードで変更されているため、問題は発生しません。

ただし、一般的に、ahmacleod の 2 番目の回答に従う場合は、RESTAdapter の dirtyRecordsForHasManyChange メソッドをオーバーライドする必要があります。それ以外の場合、シリアライザーの addHasMany は呼び出されません。これは、レコードがダーティとしてマークされていないためです。

既存のメソッドは次のようになります。

dirtyRecordsForHasManyChange: function(dirtySet, record, relationship) {
  var embeddedType = get(this, 'serializer').embeddedType(record.constructor, relationship.secondRecordName);

  if (embeddedType === 'always') {
    relationship.childReference.parent = relationship.parentReference;
    this._dirtyTree(dirtySet, record);
  }
},

したがって、次のようなものが必要になると思います。

App.Store = DS.Store.extend({
  adapter: DS.RESTAdapter.extend({
    dirtyRecordsForHasManyChange: function(dirtySet, record, relationship) {
      relationship.childReference.parent = relationship.parentReference;
      this._dirtyTree(dirtySet, record);
    },

    serializer: DS.RESTSerializer.extend({
      addHasMany: function(hash, record, key, relationship) {
        // custom ...
      }
    })
  })
});
于 2013-06-16T15:44:07.933 に答える