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?
source to share
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);
}
source to share