Reputation: 712
Where most people have problems loading embedded Ember models, I have a problem with the exact opposite.
Ember throws errors when I try to parse a record that contains an embedded
relationship, where the content for that hasMany
relation is an empty array.
How do you make an embedded Ember Data hasMany relation optional or nullable?
I have a model..
App.Beat = DS.Model.extend({
notes: DS.hasMany('note', {
embedded: 'always',
defaultValue: []
}),
...
})
This model is an association in a Bar
model, which is an association in a Track
model. Those don't really matter here.
These embedded hasMany
relationships get serialized with the following serializer..
// http://bl.ocks.org/slindberg/6817234
App.ApplicationSerializer = DS.RESTSerializer.extend({
// Extract embedded relations from the payload and load them into the store
normalizeRelationships: function(type, hash) {
var store = this.store;
this._super(type, hash);
type.eachRelationship(function(attr, relationship) {
var relatedTypeKey = relationship.type.typeKey;
if (relationship.options.embedded) {
if (relationship.kind === 'hasMany') {
hash[attr] = hash[attr].map(function(embeddedHash) {
// Normalize the record with the correct serializer for the type
var normalized = store.serializerFor(relatedTypeKey).normalize(relationship.type, embeddedHash, attr);
// If the record has no id, give it a GUID so relationship management works
if (!normalized.id) {
normalized.id = Ember.generateGuid(null, relatedTypeKey);
}
// Push the record into the store
store.push(relatedTypeKey, normalized);
// Return just the id, and the relation manager will take care of the rest
return normalized.id;
});
}
}
});
}
});
After successfully deserializing and loading the records in the store, somewhere in the application the bars
property on a Track
gets accessed. If that Bar
has beats
of which one of those beats
do not have any notes
(because it is a rest beat where no notes get played) then the following error is thrown:
"You looked up the 'bars' relationship on '' but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (DS.hasMany({ async: true }))"
This error comes from the following assertion in ember-data.js:hasRelationship:
Ember.assert("...", Ember.A(records).everyProperty('isEmpty', false));
where records
is the array of bars
that contain beats that optionally contains notes
.
So, how do I make an embedded
hasMany
relation optional so that it accepts an empty array of records?
Upvotes: 3
Views: 1247
Reputation: 712
It turned our that it was the isEmpty
on my bar
model that conflicted with the property that was being tested in the Ember assertation. Renaming this property made everything work.
Upvotes: 0
Reputation: 6366
I recommend using the EmbeddedRecordsMixin
in a recent Ember Data beta (10 or 11) and then see if you still have an issue with embedded records.
Your application serializer:
App.ApplicationSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin,{
// probably nothing required here yet
});
And then in your Beat model serializer:
App.BeatSerializer = App.ApplicationSerializer.extend({
attrs: {
notes: { embedded: 'always' }
}
});
Upvotes: 1