8

DS.Store使用するDS.RESTAdapterと、そのChatMessageように定義されたオブジェクトがあります。

App.ChatMessage = DS.Model.extend({
    contents: DS.attr('string'),
    roomId:   DS.attr('string')
});

チャット メッセージはルームに存在することに注意してください (簡単にするために表示されていません)。そのため、チャット メッセージ コントローラー (拡張Ember.ArrayController) では、ユーザーが現在いるルームのメッセージのみを読み込みます。

loadMessages: function(){ 
    var room_id = App.getPath("current_room.id");
    this.set("content", App.store.find(App.ChatMessage, {room_id: room_id}); 
}

これによりcontentが aに設定され、返されたすべてのチャット メッセージが 1 つのブロックDS.AdapterPopulatedModelArrayに表示されます。{{#each}}

次に、新しいメッセージを追加します。同じコントローラーに次のものがあります。

postMessage: function(contents) {
    var room_id = App.getPath("current_room.id");
    App.store.createRecord(App.ChatMessage, {
        contents: contents,
        room_id: room_id
    });

    App.store.commit();
}

これにより、メッセージをサーバーに保存するための ajax 要求が開始されます。これまでのところすべて問題ありませんが、ビューは更新されません。これはフィルター処理された結果であり、room_id フィルターを削除するApp.store.findと期待どおりに更新されるため、ほとんど意味があります。

this.pushObject(message)から返されたメッセージ レコードを使用しようとするとApp.store.createRecord、エラーが発生します。

結果に項目を手動で追加するにはどうすればよいですか? 私が知る限り、両方とも不変であるという方法はないようDS.AdapterPopulatedModelArrayですDS.FilteredModelArray

4

4 に答える 4

8

いくつかの考え:

(参考: https://github.com/emberjs/data/issues/190 )

データストアで新しいレコードをリッスンする方法

通常の Model.find()/findQuery() は AdapterPopulatedModelArray を返しますが、その配列は独立しています...新しいものがデータベースにロードされたことを認識しません

パラメータのない Model.find() (または store.findAll()) は、FilteredModelArray のすべてのレコードを返し、ember-data はそれをリストに「登録」し、データベースにロードされた新しいレコードはすべてに追加されます。この配列。

Model.filter(func) を呼び出すと、ストアにも登録されている FilteredModelArray が返されます...ストア内の新しいレコードにより、ember-data が「updateModelArrays」になります。trueを返すと、既存の配列に貼り付けられます。

最終的に何をしたか: ストアを作成した直後に、store.findAll() を呼び出すと、型のすべてのモデルの配列が返されます...そしてそれをストアにアタッチします...そして他の場所コードでは、ArrayObservers をこれらのリストに追加できます。次のようなものです。

App.MyModel = DS.Model.extend()
App.store = DS.Store.create()
App.store.allMyModels = App.store.findAll(App.MyModel)

//some other place in the app... a list controller perhaps
App.store.allMyModels.addArrayObserver({
   arrayWillChange: function(arr, start, removeCount, addCount) {}
   arrayDidChange: function(arr, start, removeCount, addCount) {}
})

これらの「不変」配列の 1 つにモデルをプッシュする方法:

最初に注意してください: すべての Ember-Data Model インスタンス (レコード) には clientId プロパティがあります... これは、実際のサーバー ID がまだあるかどうかに関係なく、データストア キャッシュ内のモデルを識別する一意の整数です(例: 実行直後) Model.createRecord)。

したがって、AdapterPopulatedModelArray 自体には「コンテンツ」プロパティがあります...これはこれらの clientId の配列です...そして AdapterPopulatedModelArray を反復処理すると、反復子はこれらの clientId をループし、マップする完全なモデル インスタンス (レコード) を返します。各 clientId に。

だから私がやったこと (これは「正しい」という意味ではありません!)は、これらのfindAll配列を監視し、新しいclientIdをAdapterPopulatedModelArrayのコンテンツプロパティにプッシュすることです...何かのように:

arrayDidChange:function(arr, start, removeCount, addCount){
    if (addCount == 0) {return;} //only care about adds right now... not removes...
        arr.slice(start, start+addCount).forEach(function(item) {
            //push clientId of this item into AdapterPopulatedModelArray content list
            self.getPath('list.content').pushObject(item.get('clientId'));
        });
    }

私が言えることは、「私にとってはうまくいっている」ということです:)次のember-dataの更新で壊れますか?完全に可能

于 2012-04-18T20:36:16.053 に答える
2

これにまだ苦労している人は、 store.filterメソッドを使用してDS.FilteredArray、静的ではなく動的にすることができます。type、query、そして最後に filter コールバックの3 つのパラメータを取ります。DS.AdapterPopulatedRecordArray

loadMessages: function() { 
  var self = this,
      room_id = App.getPath('current_room.id');

  this.store.filter(App.ChatMessage, {room_id: room_id}, function (msg) {
    return msg.get('roomId') === room_id;
  })
  // set content only after promise has resolved
  .then(function (messages) {
    self.set('content', messages);
  });         
}

モデル フックは promise を直接受け入れるため、余分な混乱を招くことなくモデル フックでこれを行うこともできます。

model: function() { 
  var self = this,
      room_id = App.getPath("current_room.id");

  return this.store.filter(App.ChatMessage, {room_id: room_id}, function (msg) {
    return msg.get('roomId') === room_id;
  });
}
于 2013-10-02T07:54:53.387 に答える
0

ソース (DS.Store.find) を読むと、このインスタンスで実際に受け取るのは AdapterPopulatedModelArray であることがわかります。FilteredModelArray は、レコードを作成すると自動更新されます。この動作には合格テストがあります。

于 2012-04-08T17:30:18.653 に答える