ember.js - 使用 Ember 数据和关系进行部分加载

标签 ember.js ember-data

我正在尝试编写一个 XMPP 解析器来管理一些 Ember 数据模型。信息是异步传入的,因此据我所知,它并不完全适合适配器模式。在很多情况下,我可能会获得一些信息,并且我想基于此部分更新模型。

例如,收到一条状态消息,我想保存该消息,以便创建状态历史记录,但我还想查找联系人并使用此新信息更新联系人。该联系人可能具有许多与状态无关的其他属性。联系人和状态模型之间存在一对多关系。

目前我有一些代码看起来有点像这样:

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 方法正确构建关系。但是,如果我希望将存在记录添加到存在历史记录中,则使用 set 不起作用。有趣的是,set 在处理 Presence 端时确实有效。

我发现可以通过以下方式做到这一点:

...
contact.get('presence_history').addObject(this);
...

这会添加对象,但不会触发任何观察者的更新。

我做错了什么?

最佳答案

理论上,您不必设置关系的双方。尝试遵循约定并重命名您的关联:

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);
  }

关于ember.js - 使用 Ember 数据和关系进行部分加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9739833/

相关文章:

ember.js - Ember 数据 1.0.0 : How does pluralization works?

javascript - 如何使用错误子状态在 Ember.js 中显示整页错误?

ember.js - 使用 ember.js 无限滚动(延迟加载)

javascript - 获得第一个结果的 Ember-Data objectAt() 不起作用

javascript - Ember 得不到某些属性

javascript - ember.js:扩展 Ember.TextField 并仅更新输入键上的 value 属性

javascript - 如何在 ember-cli-slick 中使用 "asNavFor"选项

cucumber - 如何对 Ember 应用程序进行 Cucumber 式验收测试?

ember.js - 模型实例的计算属性依赖于所有实例

javascript - ember-data 悲惨错误重复记录