installed versions
ember-cli 2.14.2
ember-data 2.14.10
A little perspective:
I have a service called menu
that performs store queries inside computed properties. One of these store queries is behaving rather weird. It fetches all records under the model name product-segment
from a fully functional JSON API. This model has a n-n relationship to a model called product
, referenced through hasMany
DS objects:
models/product-segment.js
export default DS.Model.extend({
products: DS.hasMany('product'),
// ...
});
models/product.js
export default DS.Model.extend({
productSegments: DS.hasMany('product-segment'),
// ...
})
The problem:
Now, when I fetch these product-segment
models, I instruct the API to { include: 'products' }
, and the API does as is requested. The response includes 15 related product
models for a particular product-segment
, which is correct.
(let's call this particular product-segment
segment x, it's the subject for all my debugging info below)
However, accessing the relationship collection on segment x from any context, at any time, only returns me 12 models, so 3 are missing. I witnessed similar issues with other product-segment
models, so I don't think it's an issue with one specific model.
More perspective
I initially thought I was dealing with a race condition of some kind, and to be sure I created a computed property - test
- to find out, and I dumped {{menu.test}}
into my view to tickle the computed prop.
Here's the bare minimum info inside services/menu.js
export default Service.extend({
store: inject(),
activeProductSegment: null,
// As a note: this does not trigger an infinite loop
productSegments: computed('store.product.[]', 'store.product-segment.[]', function() {
return get(this, 'store').findAll('product-segment', { include: 'products' });
}),
test: computed('activeProductSegment', function() {
let segment = get(this, 'activeProductSegment');
if (segment) {
console.log(segment.hasMany('products').ids());
console.log(get(segment, 'products').mapBy('id'));
}
}),
});
The property activeProductSegment
is being set to different product-segment
model instances through an action of a component , which looks like this:
export default Component.extend({
menu: inject(), // menu service is injected here...
actions: {
setProductSegment(segment) {
get(this, 'menu').set('activeProductSegment', segment);
}
}
});
The action itself works as expected, and is actually quite unrelated to my problem. activeProductSegment
is never updated in any other way. The view passes this action product-segment
model objects:
{{#each menu.productSegments as |segment|}}
<li {{action 'setProductSegment' segment}}>{{segment.name}}</li>
{{/each}}
Trouble starts here
I set menu.activeProductSegment
to segment x by clicking its associated <li>
element.
When I now try to get all related product
models of segment x, only 12 of 15 models are present within the returned collection. To be sure that the JSON response was really fine (i.e. the type definitions etc. are right) I checked the amount of product
IDs that were registered at segment x. I logged the following line (the context of the logs below is in the Ember.Service
snippet above):
console.log(segment.hasMany('products').ids());
That returned me an array with 15 correct IDs, so segment x has all id's as it is supposed to have. All product
models of those id's have been included in the response, so I suppose there should be no issue with async data of some kind. Still, the following line gave me back an array of 12 id's:
console.log(get(segment, 'products').mapBy('id'));
I tried putting the 2 logs into a 2-second setTimeout
, but the result stayed identical:
I'm starting to think this is a bug, since I noticed that the first time that an id was not accompanied by a model, is when for the first time the next ID is lower than the preceding ID.
Update on the above I tried a different order in the response, and note the second and the third id's: "7", "6"
. Guess this is not the problem:
Unless I misunderstand, the models should be live, so any relationship is supposed to update as data becomes available. I think it is very unlikely this has anything to do with malformed data.
What could be the cause for the missing models in the hasMany
relationship collection, despite the fact that all necessary ids are properly registered at the hasMany
relationship object, and we're not required to await arrival of any async/network data at this point? And what might be a suitable solution to the problem?
productSegments
gets recomputed just once? This might be tricky since it depends on'store.product.[]', 'store.product-segment.[]'
which actually change as the CP's function (this.store.findAll()
) pushes records into the store, doesn't it? This is pure guess but worth further examination – Alternatelycontent
model might but not necessarily had to load related modelslocalized-content
, I ended up checking its state as follows:// app/models/content.js isFullyLoaded: computed('localizedContent', function () { return Ember.isPresent(this.hasMany('localizedContent').value()); }),
– Alternatelyget(segment, 'products').then(()=>console.log(get(segment, 'products').mapBy('id')));
Could it be that you truly run in a race condition and explicitly requesting relationship resolution solves the problem? – Alternately