Ember.js 将项目添加到从余烬数据筛选的结果

Ember.js 将项目添加到从余烬数据筛选的结果,ember.js,ember-data,Ember.js,Ember Data,我有一个使用DS.RESTAdapter的DS.Store和一个定义如下的ChatMessage对象: App.ChatMessage = DS.Model.extend({ contents: DS.attr('string'), roomId: DS.attr('string') }); 请注意,聊天室中存在聊天信息(为简单起见,未显示),因此在我的聊天信息控制器(扩展了Ember.ArrayController)中,我只想加载用户当前所在聊天室的信息: loadMes

我有一个使用
DS.RESTAdapter
DS.Store
和一个定义如下的
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
设置为
DS.adapterPopulatedModelaray
,my view将愉快地在
{{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请求,将消息保存到服务器上,目前为止一切正常,但不会更新视图。这很有意义,因为这是一个过滤结果,如果我删除
App.store.find
上的room\u id过滤器,它会按预期更新

使用从App.store.createRecord返回的消息记录尝试
this.pushObject(message)
,会引发错误

如何手动将项目添加到结果中?就我所知,似乎没有办法,因为
DS.adapterPopulatedModelaray
DS.FilteredModelaray
都是不可变的。

我对源代码(DS.Store.find)的读取表明,在本例中实际接收到的是AdapterPopulatedModelArray。FilteredModelArray将在您创建记录时自动更新。这种行为有通过测试的机会。

所以有几点想法:

(参考资料:)

如何侦听数据存储中的新记录

一个普通的Model.find()/findQuery()将返回一个AdapterPopulatedModelArray,但该数组将独立存在。。。它不会知道任何新的内容已经加载到数据库中

不带参数的Model.find()或store.findAll()将返回FilteredModelArray中的所有记录,余烬数据将“注册”到列表中,加载到数据库中的任何新记录都将添加到此数组中

调用Model.filter(func)将返回一个FilteredModelArray,它也在商店中注册。。。存储中的任何新记录都会导致ember数据“updateModelArrays”,这意味着它将使用新记录调用筛选函数,如果您返回true,则它会将其粘贴到现有数组中

所以我最后做的是:在创建存储之后,我立即调用store.findAll(),这将返回一个类型的所有模型的数组。。。我把它贴在商店里。。。然后,在代码中的任何其他地方,我都可以将ArrayObserver添加到这些列表中。。比如:

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) {}
})
如何将模型推送到这些“不可变”数组中:

首先要注意:所有余烬数据模型实例(记录)都有clientId属性。。。这是一个唯一的整数,用于标识数据存储缓存中的模型是否具有real服务器id(例如:在执行model.createRecord之后)

因此AdapterPopulatedModelArray本身具有“内容”属性。。。这是这些客户ID的数组。。。当您在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'));
        });
    }

我能说的是:“它对我有用”:)它会在下一次余烬数据更新时中断吗?完全有可能

对于那些仍在努力解决此问题的人,您可以使用存储.filter方法获得动态的
DS.filterDarray
而不是静态的
DS.AdapterPopulatedRecordArray
。它:键入、查询,最后是一个过滤器回调

loadMessages:function(){
var self=这个,
room_id=App.getPath('current_room.id');
this.store.filter(App.ChatMessage,{room\u id:room\u id},函数(msg){
返回msg.get('roomId')==房间id;
})
//仅在承诺解决后设置内容
.then(功能(消息){
self.set('content',messages);
});         
}
您也可以在模型钩子中这样做,而不需要额外的混乱,因为模型钩子将直接接受承诺:

model:function(){
var self=这个,
room_id=App.getPath(“当前_room.id”);
返回this.store.filter(App.ChatMessage,{room\u id:room\u id},函数(msg){
返回msg.get('roomId')==房间id;
});
}

自ember.data 1.13
store.filter
被标记为要删除,请参见以下内容

该功能已可用。GitHub页面包含以下注释

我们建议您不要使用此插件进行重构。下面是三个过滤器使用场景的简短指南,以及如何最好地重构每个场景

为什么??简单地说,通过专门为您的需要定制的专门计算属性来管理自己的过滤,对您来说性能要高得多(而不是内存泄漏)


你说得对,这是一个由AdapterPopulatedModelArray公司制作的。我已经更新了问题-很抱歉输入错误!