我正在尝试编写一个XMPP解析器来管理一些Ember Data模型。信息以异步方式进入,因此AFAIK不能完全适合Adapter模式。在很多情况下,我可能会获得一些信息,我想基于此部分更新模型。
例如,状态消息到达,我想保存这个以便我可以创建状态历史记录,但我也想查找并更新这个新信息的联系人。联系人可能具有许多与状态无关的其他属性。联系人和在线模型之间存在一对多的关系。
目前我的代码看起来有点像这样:
Frabjous.Contact = DS.Model.extend({
primaryKey: 'jid',
jid: DS.attr('jidString'),
...
presence_history: DS.hasMany('Frabjous.Presence'),
});
Frabjous.Presence = DS.Model.extend({
from: DS.attr('jidString'),
...
contact: DS.belongsTo('Frabjous.Contact'),
didLoad: function(){
var contact;
var type = Frabjous.Contact;
var contact_id = this.get('from').toString();
var contact_client_id = Frabjous.Store.clientIdForId(type, contact_id);
if( Ember.none(contact_client_id) ){
// No contact exists, so create one
Frabjous.Store.load(type,{jid: this.get('from'), presence_history:[this.get('id')]});
contact = Frabjous.Store.find(type,contact_id);
}else{
// Update contact
contact = Frabjous.Store.find(type,contact_id);
// !!! this DOES NOT work
var history = contact.get('presence_history');
history.addObject(this);
contact.set('presence_history',history);
}
// !!! this DOES work
this.set('contact',contact);
}
当出现新的状态消息时,如果不存在联系人,则会创建一个,并使用load方法正确构建关系。但是,如果我希望将状态记录添加到presence_history,则使用set
不起作用。有趣的是,set
在处理存在方面时确实有效。
我发现可以这样做:
...
contact.get('presence_history').addObject(this);
...
这会添加对象,但不会触发任何观察者的更新。
我做错了什么?
答案 0 :(得分:0)
理论上,你不应该设置关系的两个方面。请尝试遵循约定并重命名您的关联:
Frabjous.Contact = DS.Model.extend({
primaryKey: 'jid',
jid: DS.attr('jidString'),
...
presences: DS.hasMany('Frabjous.Presence'),
});
然后简单地关联您的记录
if( Ember.none(contact_client_id) ){
// No contact exists, so create one
Frabjous.Store.load(type,{jid: this.get('from'), presence_history:[this.get('id')]});
contact = Frabjous.Store.find(type,contact_id);
}else{
// Update contact
contact = Frabjous.Store.find(type,contact_id);
this.set('contact', contact);
}
如果您不想更改JSON,可以随时配置模型,为关联指定不同的密钥。
另外,我建议您使用hasReferenceForId
而不是直接操作clientIdForId
。
Frabjous.Presence = DS.Model.extend({
from: DS.attr('jidString'),
...
contact: DS.belongsTo('Frabjous.Contact'),
didLoad: function(){
var contact;
var type = Frabjous.Contact;
var contact_id = this.get('from').toString();
var store = DS.defaultStore;
if( !store.hasReferenceForId(Frabjous.Contact, contact_id) ){
// No contact exists, so create one
Frabjous.Store.load(type,{jid: this.get('from'), presence_history:[this.get('id')]});
contact = Frabjous.Store.find(type,contact_id);
}else{
...
}
// !!! this DOES work
this.set('contact',contact);
}