Partial Loads Using Ember Data and Relations

I am trying to write an XMPP parser that will manage some Ember Data models. The information comes in asynchronously, so AFAIK doesn't fit neatly into the adapter template. There are many cases where I might get some information and I want to partially update the model based on that.

For example, a presence message appears, I want to save it to create a status history, but I also want to find and update a contact with this new information. A contact can have many other attributes that have nothing to do with presence. There is a one-to-many relationship between contact and presence.

At the moment I have some code that looks something like this:

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

      

When a new presence message arrives, if the contact does not exist, it will create it and build the relationship correctly using the download method. However, if I want to add a presence record to history_history, then the usage set

doesn't work. I wonder what set

works when dealing with the presence side.

I found that it can be done with:

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

      

This adds the object, but does not trigger updates for any of the observers.

What am I doing wrong?

+3


source to share


1 answer


In theory, you don't need to establish both sides of the relationship. Try the conventions and rename your association:

Frabjous.Contact = DS.Model.extend({
  primaryKey: 'jid',
  jid:        DS.attr('jidString'),
  ...
  presences: DS.hasMany('Frabjous.Presence'),
});

      

And then just match your entries

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

      



If you don't want to change your JSON, you can always configure your model to specify a different key for your association.

Also, I recommend using hasReferenceForId

direct control instead 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);
  }

      

0


source







All Articles