I've two models:
ticket:
export default DS.Model.extend({
name: DS.attr('string'),
email: DS.attr('string'),
messages: DS.hasMany('message'),
})
messages:
export default DS.Model.extend({
message: DS.attr('string'),
date: DS.attr('date'),
ticket: DS.belongsTo('ticket', { async: true }),
});
And a router with this model method:
model(params) {
return this.get('store').findRecord('ticket', params.id, {reload: true, include: 'messages'});
},
At the page reload all ok, only a call to tickets/:id is made but sometimes ember make a bunch of calls to messages/:id. Why don't use the included data and try to retrieve from the server?
I've tried async: false on hasMany relation but I've this error:
Error: Assertion Failed: You looked up the 'messages' relationship on a 'ticket' with id 15 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 })`)
Any idea?
This is the GET tickets/:id response:
{"data":
{
"id":"15",
"type":"tickets",
"attributes":{...},
"relationships":{"messages":{"data":[{"id":"1478482584658","type":"messages"},{"id":"1478482588516","type":"messages"},{"id":"1478517720","type":"messages"},{"id":"1478517813","type":"messages"},{"id":"1478517893","type":"messages"},{"id":"1478530030","type":"messages"},{"id":"1478530032","type":"messages"},{"id":"1478533446","type":"messages"}]}}},
"included":[
{"id":"1478482584658","type":"messages","attributes":{...}},{"id":"1478482588516","type":"messages","attributes":{...}},
...
}
}
]
}
Why don't take data from included and make other calls to the server?
What about promise?
While working with relationships it is important to remember that they return promises.
https://guides.emberjs.com/v2.1.0/models/working-with-relationships/#toc_relationships-as-promises
Related
DEBUG: Ember : 1.7.1
DEBUG: Ember Data : 1.0.0-beta.12
DEBUG: Handlebars : 1.1.2
DEBUG: jQuery : 1.10.2
Having an issue with what I believe is the belongsTo attribute on my user model. (This happens on my other belongsTo attributes within my application as well). I have a Django backend which returns a response when I comment out the network: attribute.
{
email: "test#test.com",
first_name: "Test",
global_code: "daht64q691zy4k887ch",
global_id: "GBID-USER-dat64q6917zy4k887ch",
institution_gbid: "GBID-GINS-567j53ey0lojsu2kys",
institution_name: "Some University",
last_name: "Testing",
network: { },
view_policy: {
capability: "system:view",
description: "Anyone can view a user",
hold: true,
id: "daht64q691y4k887ch:system:view",
values: ""
}
}
Code for the User Model:
App.User = DS.Model.extend({
first_name: DS.attr('string'),
last_name: DS.attr('string'),
global_id: DS.attr('string'),
network: DS.belongsTo('basicgrouping')
}):
Code for Basic Grouping model:
App.Basicgrouping = DS.Model.extend({
global_id: DS.attr('string'),
name: DS.attr('string'),
gbid_code: function(){
return getGBIDCode(this.get('global_id'));
}.property('global_id')
});
Debugging ember-data I placed a console.log() within the following code:
relationshipsByName: Ember.computed(function() {
var map = Map.create();
this.eachComputedProperty(function(name, meta) {
console.log(name, meta);
if (meta.isRelationship) {
meta.key = name;
var relationship = relationshipFromMeta(this.store, meta);
relationship.type = typeForRelationshipMeta(this.store, meta);
map.set(name, relationship);
}
});
This seems to show that the type of the object that it belongs to is not being found (Basicgrouping) as it's returning App.undefined.
My theory is it may have something to do when parsing the server response and maybe the payload response. This also happens in other belongTo relationships in my code.
It turns out that there was a file that was overriding some of the DS. methods and causing an empty type to be sent. I was in the process of removing use of the shim but didn't know that it was being used.
Thanks the Bmacs from the ember community for the help debugging the issue.
I need to navigate through my relationships inside a controller and have not figured out how to do it. I have the following models.
// models/asset.js
export default DS.Model.extend({
name: DS.attr('string'),
type: DS.belongsTo('lookup', {inverse: null, async: true}),
children: DS.hasMany('asset', {inverse: 'parent', async: true}),
parent: DS.belongsTo('asset', {inverse: 'children', async: true})
});
// models/lookup.js
export default DS.Model.extend({
value: DS.attr('string'),
children: DS.hasMany('lookup', {inverse: 'parent', async: true}),
parent: DS.belongsTo('lookup', {inverse: 'children', async: true})
});
The type of my current asset is based on the child records of the parent asset.
In an action in the controller I need to get the current asset's parent's type's children. I would like to just use:
return this.store.findAll('lookup', this.get('asset.parent.type.children')).then(function(parentTypeChildren) {});
But life is not so easy.
If I have the asset loaded and I do this.get('asset.parent') do I get the full asset record or just the parent asset ID?
Any hints about this? All help will be greatly appreciated.
Since you have async: true, a this.get('asset.parent') would trigger a server call (if it is not already in the store) and fetch the parent asset (as a set call) and return it as a promise. this.get('asset.data.parent') would return the id of the parent.
So basically you should try something like this (under the assumption that the asset.parent.type is already in your store):
var childrenLookUps = this.get('asset.parent.type.children');
childrenLookUps.then(function(){
// do something with your childrenLookUps
});
While using the RESTAdapter, I have an Organization model which is to be embedded in the response. It appears that the default implementation of the Ember.RESTAddapter sends the id, using the same model name, but not as an object (this currently 'works'):
POST/PUT api/v1/item/{id}
{
"item" {
id: "1029383829"
...
organization: "26044097612186763401268824297"
}
}
I have consulted the documentation, and found that the mixin DS.EmbeddedRecordsMixin should do this, coupled with declaring embedded: "always" on the attrs or the Serializer:
models/item.js
var Item = DS.Model.extend({
...,
organization: DS.belongsTo("organization", {embedded: "always"})
});
serializers/item.js:
var ItemSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
organisation: {serialize: "id", embedded: "always"}
}
}
);
However, when deserializing records, Ember Data complains, saying that it expected an object, but just got a string:
Assertion Failed: Expected an object as data in a call to push for
app#model:organization: , but was 26044097612186763401268824297
Ultimately, I would prefer a system, likened to sideloading, wherein an additional attribute, post-fixed "_id", describes the corresponding id of an embedded record:
{
"item": {
id: 1,
name: "name",
organization_id: "26044097612186763401268824297"
...
}
}
How can I allow serializing and deserializing embedded id sideloading for my Organization model?
You aren't actually embedding the record, you're just specifying the id, in that case you should mark it as async.
var Item = DS.Model.extend({
...,
organization: DS.belongsTo("organization", {async: true})
});
And remove your embedded records implementation.
I created model Consultation:
import DS from 'ember-data';
export default DS.Model.extend({
title: DS.attr('string'),
records: DS.hasMany('record', { async: true }),
currentUser: DS.belongsTo('user'),
remoteUser: DS.belongsTo('user')
});
And also I created model Record:
import DS from 'ember-data';
export default DS.Model.extend({
record_text: DS.attr('string'),
record_poster_id: DS.attr('string'),
record_consultation_id : DS.attr('number'),
consultation: DS.belongsTo('consultation'),
isMine: DS.attr('boolean')
});
At first all consultations load during opening page. And I don't want to load all records of each consultation during opening page. To do this I added async: true but all records loaded simultaneously sending many requests like /consultations/:id/records. After that consultation and records still non-joined. I have next json response for consultation:
{
"consultations":[
{
"id":140721,
"title":"ExpertId: 41217, clientId: 0",
"links":{
"records":"records"
},
"currentUser":41217,
"remoteUser":159984
},
......
]
}
And for records:
{
"records":[
{
"record_id":681952,
"record_consultation_id":140721,
"record_poster_id":0,
"record_text":"1",
},
........
]
}
I think I need to override default serializer. I tried to create serializer for Record:
import DS from 'ember-data';
export default DS.RESTSerializer.extend({
primaryKey: 'record_id',
keyForRelationship: function(key, kind) {
return 'record_consultation_id';
}
});
But it still doesn't work.
Please advise how to join models using links?
UPDATE:
Template
{{#each item in model.records}}
<div class="table message">
{{item.record_text}}
</div>
{{/each}}
I am doing Async (lazy loading) of data using RESTAdaptor and Ember-Data too.
For my links area, i put in the full request URL as follows:
"links":{
"records":"/consultations/140721/records"
},
And using firebug to look at when the request gets sent off, its only when I request for the async content that the AJAX gets fired off.
model.get('records');
Can you provide your Controllers & Template code so I can see how your accessing the Records?
Using Ember-data and Ember.js, I'm trying to load two models with one JSON request. The models have a relationship analogous to this:
App.Person = DS.Model.extend({
name: DS.attr('string'),
dogs: DS.hasMany('App.Dog'),
});
App.Dog = DS.Model.extend({
name: DS.attr('string'),
owner: DS.belongsTo('App.Person'),
});
My server is sending JSON like this:
{
"dog": {
"id": 1,
"name": "Fido",
"owner": {
"id": 1,
"name": "John Smith",
"dogs": [1]
}
}
}
…And yet, Ember-data still sends a request (using findQuery) to my server trying to get the owner JSON.
I have a jsFiddle set up that demonstrates it here. To watch the problem happen, you'll need to go to this link to activate the route/template:
http://fiddle.jshell.net/6kQ8s/2/show/#/dog/1
I haven't defined findQuery() in my adapter on purpose because I shouldn't need that to get data that I have already sent… Right?
Does anyone know what I'm doing wrong here?
I'm doing the following (using ember-data revision 8)
App.Dog = DS.Model.extend({
name: DS.attr('string'),
owner: DS.belongsTo('App.Person', { embedded: true }),
});
Additionally, I have to tell the serializer to load a mapping for this relation.
Though it's not required, I'm using my own DS.Serializer subclass. At initialisation
time the serializer loads a mapping for the Person class, which specifies that
embedded relationships should be loaded.
App.WOSerializer = DS.Serializer.extend({
init: function(){
this._super();
this.map(App.Dog, {
person: {
embedded: 'load'
}
});
});
Edit by question asker:
The serializer needed to be initialized in the adapter.
App.adapter = DS.Adapter.create({
// ...
serializer: App.WOSerializer.create()
});
Try use embedded property.
App.Dog = DS.Model.extend({
name: DS.attr('string'),
owner: DS.belongsTo('App.Person', { embedded: true }),
});