Ember data, how can i use nested(two-depth) json-format for hasMany Relationship - ember.js

Generally, Ember HasMany relationship json format is follow,
{ "post" : { id:1, title:"this is title", comments:[1,2], writer: ...} }
But, i want to use next json format (because, my server return like this)
{ "post" : { id:1, title:"this is title",
comments:[
{id:1, bodytext:"blarblar...."},
{id:2, bodytext:"second blarblar...."},
], writer: ...} }
How can I use this?
Isn't there any problem in ember store relationship?

This is a job for EmbeddedRecordsMixin.
If you're implementing the server yourself and it's purpose-built for your ember application, you should consider switching to side-loading instead:
{ "post" : { id: 1,
title: "this is title",
comments: [1,2],
writer: ...
},
"comments": [ { id: 1,
bodytext: "blarblar...."
},
{ id: 2,
bodytext: "second blarblar...."
}
]
}
That way, it would be still just one request, but would work for more complicated structures (other than trees) as well.

Related

Ember data Embedded JSON without Id and no root object

I am working with Ember and Ember-data. But the JSON which i receive is not par with the Ember side-loading standards. The JSON does'nt have a root model. Also the models are embedded and some times haves Ids and sometimes does not have Id.
I have seen couple of links on how to add root model using extract hook and also how to play with embedded model using
App.ColorSerializer = DS.RestSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
foos: {embedded: 'always'}
}
});
This code is taken from this link.
This is the JSON used there
{
colors:[
{
id: 1,
color: "red",
foos:[
{
id:1,
name:'something 1'
},
{
id:2,
name:'something 2'
}
]
},
...
Now the problem that i am facing is that my JSON could also look like below(no root model "color")
{
id: 1,
color: "red",
foos:[
{
id:1,
name:'something 1'
},
{
id:2,
name:'something 2'
}
]
},
...
or even like this(without Ids for foo objects)
{
id: 1,
color: "red",
foos:[
{
name:'something 1'
},
{
name:'something 2'
}
]
},
...
Is there any way i can handle this? How do i add Ids to the embedded model foo? Also is there some solution/plugin which would accept any kind of embedded JSON and convert it into side loaded JSON and added Ids if needed.
I have seen this solution. Does it really work? Because it does not use the latest EmbeddedRecordsMixin
I used a generic transform for arrays:
// /transforms/array.js
import DS from "ember-data";
import Ember from "ember";
export default DS.Transform.extend({
deserialize: function (value) {
if (Ember.isArray(value)) {
return Ember.A(value);
} else {
return Ember.A();
}
},
serialize: function (value) {
if (Ember.isArray(value)) {
return Ember.A(value);
} else {
return Ember.A();
}
}
});
Then in my model, I simply use:
foos: DS.attr("array")

Ember-data return a single json object with store.find

Is this possible? I know I can do:
this.store.find('model', 1)
but that's not what I want. I would like to retrieve the json in this format: (working if I retrieve it in the route like this ):
App.OptionsRoute = Ember.Route.extend({
model: function () {
return {
"options":{
"id": "1",
"headline": "A Headline",
"results": [
{
"id": "1",
"title": 'Option 1',
},
{
"id": "2",
"title": "Option 2"
}
]
}
};
}
});
options model:
App.Options = DS.Model.extend({
headline: DS.attr(),
results: DS.attr()
});
options.hbs
<h5>{{options.headline}}</h5>
{{#each item in options.results}}
<h5>{{item.title}}</h5>
{{/each}}
I am using the RESTAdapter. And that is the only model that will be retrieved on that route. I would like to be able to use ember-data, but store.find expects an array.
You're missing a point here. First of all you're using bad format for your response. You need custom serializer. You can also use a bit more dirty workaround like this(but it works). Route:
App.OptionsRoute = Ember.Route.extend({
model: function() {
that = this;
return new Promise(function (resolve, reject) {
url = that.store.adapterFor('option').buildURL('option');
Ember.$.getJSON(url).then(function (json) {
body = json.options;
correct = {
options: [
body
]
};
that.store.pushPayload('option', correct);
resolve(that.store.all('option').get('firstObject'));
});
});
}
});
Template:
<h5>{{model.headline}}</h5>
{{#each item in model.results}}
<h5>{{item.title}}</h5>
{{/each}}
Application outputs:
A Headline
Option 1
Option 2
Working demo - please notice that I'm using $.mockjax to recreate your response from server, but it matches format you provided.

EmberJS auto loading inverse relations?

I have a model like:
var Survey = DS.Model.extend({
title: DS.attr('string'),
});
and:
var SurveySection = DS.Model.extend({
survey: DS.belongsTo('survey', {async:true}),
title: DS.attr('string'),
help_text: DS.attr('string'),
});
If i have a survey object, can I just do survey.get('survey_section') to get all the sections associated with a particular survey, because this isn't working? It doesn't even work if I add a survey_sections: DS.hasMany('survey_sections', {async:true}) to my survey model.
I should add that I'm using fixtures. When I release the app they'll still be used (ie so if the RESTAdapater would fix it, that's not a fix in my case):
Survey.reopenClass({
FIXTURES: [
{
"id": 1,
"title": "Favourite food"
},
{
"id": 2,
"title": "Sports"
}
]
});
and:
SurveySection.reopenClass({
FIXTURES: [
{
"help_text": "",
"id": 1,
"survey": 1,
"title": "Italian food"
},
{
"help_text": "",
"id": 2,
"survey": 1,
"title": "Team sports"
}, ...]});
Is the fixture adapter not able to retrieve related records in the reverse direction like this? If not, will I have to go the laborious route of manually getting the sections with survey=1, for example (laborious because I'll have to take this approach throughout my whole app with other models)?
Update
Specifically my failing code is (with survey 1):
this.get('survey').get('survey_sections').then(function(survey_sections) {
// survey_sections contains no objects, so objectAt(0) returns undefined.
survey_sections.objectAt(0).get('questions').then(function(questions) {
console.log('Set first question ID to ' + self.get('firstQuestionId'));
});
});
As the fixtures show there should be 2 SurveySection objects in survey_sections, but instead none are found.
I didn't want to do it, but I had to add the forward relation to the items in the Survey fixture, e.g.:
Survey.reopenClass({
FIXTURES: [
{
"id": 1,
"title": "Favourite food",
"survey_sections": [1, 2],
},
{
"id": 2,
"title": "Sports",
"survey_sections": [3],
}
]
});
and update the Survey model with:
survey_sections: DS.hasMany('survey_sections', {async:true})

What is the format expected by a find(id) request?

My backend replies to find all requests:
User.find();
Like this
{ 'users' : [ user1_obj, user2_obj ] }
Ember-data is happy about it. Now if I do a simple single object find:
User.find('user1');
I have tried configuring the backend to return any of the following:
user1
{ 'user1' : user1_obj }
{ 'user' : { 'user1' : user1_obj } }
{ 'user' : user1_obj }
But none of those are working. What should I return from the backend in reply to find("obj-id") requests? According to the documentation about JSON ROOT, the right format looks like:
{ 'user' : user1_obj }
Ember does not complain about it, but the Ember Objects processed have a very strange structure, like this:
As you can see, _reference.record is referring to the top record. Also (not shown here) _data field is empty.
What could be causing that strange nesting?
EDIT
As linked by mavilein in his answer, the JSON API suggests using a different format for singular resources:
{ 'users' : [user1_obj] }
That means, the same format as for plural resources. Not sure if Ember will swallow that, I'll check now.
Following this specification, i would suspect the following:
{
'users' : [{
"id": "1",
"name" : "John Doe"
},{
"id": "2",
"name" : "Jane Doe"
}]
}
For singular resources the specification says:
Singular resources are represented as JSON objects. However, they are
still wrapped inside an array:
{
'users' : [{
"id": "1",
"name" : "John Doe"
}]
}
Using User.find() will expect the rootKey pluralized and in your content an array of elements, the response format is the following json:
{
users: [
{ id: 1, name: 'Kris' },
{ id: 2, name: 'Luke' },
{ id: 3, name: 'Formerly Alex' }
]
}
And with User.find(1) the rootKey in singular, and just one object:
{
user: {
id: 1, name: 'Kris'
}
}
Here a demo showing this working

ExtJS 4.1.0 proxy returns update api instead of create

I was working on a code which was about integrating ExtJS 4 and Django. The link is:
https://github.com/diegocmsantos/extjs4-tdc2011-django
It works fine on ExtJS 4.0.0. But when I upgrade to 4.1.0 it's proxy returns update api instead of create.
I have added the 'idProperty' parameter to the Model, but still gives me the same result.
Model class:
Ext.define('TDC2011.model.Contact', {
extend: 'Ext.data.Model',
idProperty: 'id',
fields : [
{ name : "id", type : "int", mapping : "#id" },
{ name : "name", type : "string"},
{ name : "phone", type : "string"},
{ name : "email", type : "string"}]
});
Store Class:
Ext.define('TDC2011.store.Contacts', {
extend: 'Ext.data.Store',
model: 'TDC2011.model.Contact',
autoLoad: true,
pageSize: 35,
autoLoad: {start: 0, limit: 35},
proxy: {
type: 'ajax',
api: {
read : 'contact/view.action',
create : 'contact/create.action/',
update: 'contact/update.action/',
destroy: 'contact/delete.action/'
},
reader: {
type: 'json',
root: 'data',
successProperty: 'success'
},
writer: {
type: 'json',
writeAllFields: true,
encode: false,
root: 'data'
},
listeners: {
exception: function(proxy, response, operation){
Ext.MessageBox.show({
title: 'REMOTE EXCEPTION',
msg: operation.getError(),
icon: Ext.MessageBox.ERROR,
buttons: Ext.Msg.OK
});
}
}
}
});
Is there anyone who knows the main cause of problem?