3

バックグラウンド

最近、Tom Daleは、「埋め込み読み込みが復活しました!」と発表しました。ただし、ロードシナリオで完全にサポートされているように見えます。組み込みアソシエーションのシリアル化がまだ開発中であるのか、それともユーザーがカスタムシリアライザーを構築して自分で実装することが期待されているのかは不明です。

要件

埋め込まれた関連付けのJSONは次のようになります。

{
  inputs: [
    {
      id: 1,
      name: "Favorite Color",
      type: "SelectInput",
      options: {
        choices: [ 'red', 'green', 'yellow' ]
      }
    },   
    {
      id: 2,
      name: "email",
      type: "TextInput",
      options: {}
    }
  ]
}

これを表す「残り火の方法」は、JSONを次のようなモデルに変換するカスタムシリアライザーを構築することだと思います。

App.Choice = DS.Model.extend({
  name: DS.attr( 'string' ),
  input: DS.belongsTo( 'App.Input' )
});

App.Input = DS.Model.extend({
  name: DS.attr( 'string' ),
  type: DS.attr( 'string' ),
  choices: DS.hasMany( 'App.Choice' )
});

試みられた解決策

次の解決策はほとんど機能しますが、多くのコードをリバースエンジニアリングしてサブクラス化する必要があるため、「間違ったことをしている」必要があるように感じます。

Customizer.MyRESTAdapter = DS.RESTAdapter.extend({
  dirtyRecordsForAttributeChange: function(dirtySet, record, attributeName, newValue, oldValue) {
    if(record.constructor === Customizer.Choice) {
      if(newValue === oldValue) { return; }

      var input = null;
      if (attributeName == 'name') {
        input = record.get('input');
      }
      else if(attributeName == 'input') {
        input = newValue;
      }
      if( input ) {
        dirtySet.add( input );
      }
    }
    else {
      this._super(dirtySet, record, attributeName, newValue, oldValue);
    }
  },

  dirtyRecordsForBelongsToChange: function(dirtySet, child, relationship) {
    if(child.constructor === Customizer.Choice) {
      var input = child.get( 'input' );
      if( input ) {
        dirtySet.add( input );
      }
    }
    else {
      this._super(dirtySet, child, relationship);
    }
  },

  dirtyRecordsForHasManyChange: function(dirtySet, parent, relationship) {
    this._super(dirtySet, parent, relationship);
  }
});

Customizer.MyRESTSerializer = DS.RESTSerializer.extend({
  init: function() {
    this._super();
    this.mappings.set( 'Customizer.Input', { choices: { embedded: 'load' } } );
  },

  extractEmbeddedHasMany: function(type, hash, key) {
    if(type == Customizer.Input) {
      if(!(hash['options'] && hash['options']['choices'])) { return null; }

      var choices = [];
      hash['options']['choices'].forEach(function(choice, i){
        var choiceId = hash['id'] + '_' + i;
        var inputId = hash['id'];
        choices[i] = { id: choiceId, input_id: inputId, name: choice };
      });
      return choices;
    }

    return this._super(type, hash, key);
  },

  addHasMany: function(data, record, key, relationship) {
    this._super(data, record, key, relationship);

    if( key === 'choices' ) {
      var choices = record.get('choices').map(function( choice ){
        return choice.get( 'name' );
      });
      data['options'] = data['options'] || {};
      data['options']['choices'] = choices;
    }
  }

});

Customizer.store = DS.Store.create({
  revision: 10,
  adapter: Customizer.MyRESTAdapter.create({
    namespace: 'api/v1',
    bulkCommit: false,
    serializer: Customizer.MyRESTSerializer
  })
})

フィードバックのリクエスト

  • これは正しい道ですか?
  • 残り火チームはこれを行うためのより良い方法に積極的に取り組んでいますか?
4

2 に答える 2

1

ember-dataのembedded-recordsブランチを確認してください: https ://github.com/emberjs/data/commits/embedded-records

特に、埋め込みデータの保存については、次のコミットを参照してください: https ://github.com/emberjs/data/commit/0abd3b965c50dfeb23bd8ff50751825482050e68

埋め込まれたレコードの完全なサポートはすぐそこにあります:)

アップデート

埋め込みレコードブランチは、2012年12月28日にマスターにマージされました。

https://github.com/emberjs/data/commit/b5d7c478e79aa9706e0196b8769b7ef67bb26fc4

于 2012-12-19T03:44:40.483 に答える
0

最終的にhttp://mozmonkey.com/2013/12/serializing-embedded-relationships-ember-data-beta/のバリエーションを使用しました。私の場合、idJSONにを追加するか、汚れていない場合はid、それ自体を送信します。

class App.ApplicationSerializer extends DS.ActiveModelSerializer
  # Based on http://mozmonkey.com/2013/12/serializing-embedded-relationships-ember-data-beta/
  # Also see http://discuss.emberjs.com/t/ember-data-beta-3-and-saving-hasmany-relationships-with-activemodelserializer`-and-rails/3167
  serializeHasMany: (record, json, relationship) ->
    key = relationship.key
    hasManyRecords = Ember.get(record, key)
    embed = relationship.options.embed
    if embed && hasManyRecords
      json[key] = []
      hasManyRecords.forEach (item, index) =>
        json[key].push @serializeItem(item, embed)
    else
      @._super(record, json, relationship)

  serializeBelongsTo: (record, json, relationship) ->
    key = relationship.key
    belongsToRecord = Ember.get(record, key)
    embed = relationship.options.embed
    if embed
      json[key] = @serializeItem(belongsToRecord, embed)
    else
      @._super(record, json, relationship)

  serializeItem: (item, embed) ->
    if embed == 'ifDirty'
      if item.isDirty
        data = item.serialize()
      else
        data = {}
      data['id'] = item.id
    else if embed == 'always'
      data = item.serialize()
      data['id'] = item.id
    else
      null
    data
于 2014-04-11T17:07:15.933 に答える