How to embed model in model (nest records) using ember-data? - ember.js

I am trying to setup embedded records in my project using Ember-cli.
I can't get it working, I tried different configurations with {embedded: "always", etc...} but all I get is: Error: Assertion Failed: You must include an id for user in an object passed to push Please help.
I'm using
DEBUG: -------------------------------
DEBUG: Ember : 1.12.1
DEBUG: Ember Data : 1.13.4
DEBUG: jQuery : 2.1.4
DEBUG: Ember Simple Auth : 0.8.0
DEBUG: -------------------------------
My JSON with QuestionDefinitions is:
{
"data": [
{
"created": 1439824135440,
"updated": 1439824135440,
"userID": 20,
"user": {
"password": null,
"created": null,
"updated": null,
"photoID": null,
"photo": null,
"email": "super#duper.com",
"emailConfirmed": false,
"phoneNumber": null,
"phoneNumberConfirmed": false,
"accessFailedCount": 0,
"id": 20,
"userName": "qwerty"
},
"addCategoriesIDs": [],
"removeCategoriesIDs": [],
"recommendations": [],
"removeRecommendstionIDs": [],
"patternAnswers": [],
"removePatternAnswerIDs": [],
"hint": null,
"version": 1,
"commonVersion": 2,
"id": 1,
"questionText": "Test?",
"weight": 0,
"answerType": 0,
"status": 0,
"estimatedTime": null,
"private": false
},
{
"created": 1439824143340,
"updated": 1439824143340,
"userID": 20,
"user": {
"password": null,
"created": null,
"updated": null,
"photoID": null,
"photo": null,
"email": "super#duper.com",
"emailConfirmed": false,
"phoneNumber": null,
"phoneNumberConfirmed": false,
"accessFailedCount": 0,
"id": 20,
"userName": "qwerty"
},
"addCategoriesIDs": [],
"removeCategoriesIDs": [],
"recommendations": [],
"removeRecommendstionIDs": [],
"patternAnswers": [],
"removePatternAnswerIDs": [],
"hint": null,
"version": 1,
"commonVersion": 3,
"id": 2,
"questionText": "Test?",
"weight": 0,
"answerType": 0,
"status": 0,
"estimatedTime": null,
"private": false
}
]
}
QuestionDefinition model is:
//app/models/questiondefinition.js
import Ember from 'ember';
import DS from "ember-data";
export default DS.Model.extend({
//id : DS.attr('string'), //sie nie uzywa
created : DS.attr('pl-date'),
updated : DS.attr('pl-date'),
userID : DS.attr('number'),
user : DS.belongsTo('user',{async: false, embedded: 'always'}),
//hint : DS.attr('string'),
hint : null,
version : DS.attr('number'),
commonVersion : DS.attr('number'),
questionText : DS.attr('string'),
weight : DS.attr('number'),
answerType : 0,
status : 0,
estimatedTime : DS.attr('number'),
"private" : DS.attr('boolean'),
questionDefLegalBasis: function () {
return this.get('questionText').length % 2 > 0;
}.property('questionText'),
/**
* One-to-many
*/
patternAnswers : DS.hasMany('patternanswer'),
recommendations: DS.hasMany('recommendation'),
categories : DS.hasMany('questiondefinitioncategory', {async: true}),
comments : DS.hasMany('questiondefinitioncomment', {async: true})
});
User model is:
//app/models/user.js
import Ember from 'ember';
import DS from "ember-data";
export default DS.Model.extend({
"password": DS.attr('string'),
"created": DS.attr('pl-date'),
"updated": DS.attr('pl-date'),
"photoID": DS.attr('number'),
"photo": DS.attr('string'),
"email": DS.attr('string'),
"emailConfirmed": DS.attr('boolean'),
"phoneNumber": DS.attr('string'),
"phoneNumberConfirmed": DS.attr('boolean'),
"accessFailedCount": DS.attr('number'),
"userName": DS.attr('string'),
/**
* One-to-many
*/
//questionDefinitions : DS.hasMany('questiondefinition'),
questionDefinitionComments : DS.hasMany('questiondefinitioncomment'),
patternAnswers : DS.hasMany('patternanswer'),
});
And last but not least, serializer:
//app/serializers/questiondefinition.js:4
import DS from "ember-data";
function removeErrorsIfEmtpy(payload) {
if (typeof payload.errors !== 'undefined' && payload.errors.length === 0) {
delete payload.errors;
}
}
export default DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs : {
user: {embedded: 'always',
serialize : 'record',
deserialize: 'record'
}
//comments: { serialize: 'ids' }
},
extractArray : function (store, type, payload) {
payload.questiondefinitions = payload.data;
delete payload.data;
removeErrorsIfEmtpy(payload);
//console.log(arguments);
//return this._super(store, type, payload);
return this._super.apply(this, arguments);
},
extractSingle: function (store, primaryTypeClass, payload, recordId) {
payload.questiondefinition = payload.data;
delete payload.data;
removeErrorsIfEmtpy(payload);
//return this._super(store, primaryTypeClass, payload, recordId);
return this._super.apply(this, arguments);
}
});

This enigmatic question could be without answer to the next 20m of Stack, but here is the answer.
Looking at the questiondefinition serializer one sees that there is tampering with payload because server responses with objects kept in 'data' property.
The enigmatic error Error: Assertion Failed: You must include an id for user in an object passed to push led me to the source of ember-data where I find out that I didn't prepared serializer for user model. So ember just wanted the user properties but all it could get it was 'data' property. So remember, always keep your serializers up to date.
That's IT!

Related

ember JS returns only the last value from tastypie

I'm trying to get a list of items served from Django and Tastypie and display them using Ember.js. I've encountered the following problem:
EmberJS stores only the last value from JSON - so /api/post serves a few entries, but EmberJS stores and then displays only the last one(I also checked with the Ember extensions for Chrome). I'm not even sure where to look for a solution - is it Ember, Ember-data, Tastypie or all of them?
Here's the javascript code:
Blog.ApplicationAdapter = DS.DjangoTastypieAdapter.extend({
host: "http://127.0.0.1:8000",
namespace: "api/v1"
});
Blog.ApplicationSerializer = DS.DjangoTastypieSerializer.extend({});
/* Models */
Blog.Post = DS.Model.extend({
title: DS.attr('string'),
body: DS.attr('string'),
added: DS.attr('date'),
created: DS.attr('date')
});
/* Routes */
Blog.Router.map(function() {
this.route('post-list');
this.route('post', { path: 'post_id' });
});
Blog.IndexRoute = Ember.Route.extend({
redirect: function() {
this.transitionTo('post-list')
}
});
Blog.PostListRoute = Ember.Route.extend({
model: function() {
return this.store.find('post')
}
});
Here's the curl extract for reference:
{
"meta": {
"limit": 20,
"next": null,
"offset": 0,
"previous": null,
"total_count": 2
},
"objects": [
{
"added": "2014-12-23T19:49:28.881759",
"body": "hsdkfkjahsdkshufy \r\n\r\nLorem ipsum",
"created": "2014-12-23T19:49:28.881759",
"id": 2,
"resource_uri": "\/api\/v1\/post\/2",
"slug": "jklshfkjasfhkjkhlf",
"title": "jkl;shfkjasfhkjkhlf"
},
{
"added": "2014-12-23T23:00:23.719586",
"body": "sdhkjasgaskg slkhs;fas\r\n\r\nhsdkjhsask sfhjask \r\nhakjhagkl\r\n\r\nhgaskjhagskj \r\nhgkjash",
"created": "2014-12-23T23:00:23.719586",
"id": 3,
"resource_uri": "\/api\/v1\/post\/3",
"slug": "asfhklasdnhjasdkghskl",
"title": "asfhklasdnhjasdkghskl"
}
]
}
I recreated the project using latest Django version (from 1.6 to 1.7). It seems that the issue is solved now, no changes in the code were made.

Connecting to Express/Mongoose backend Ember-data rejects with "Object has no method 'eachTransformedAttribute'"

I'm using ember-data:
// Version: v1.0.0-beta.3-2-ga01195b
// Last commit: a01195b (2013-10-01 19:41:06 -0700)
var App = Ember.Application.create();
App.Router.map(function() {
this.resource("main");
});
Using a namespace:
App.ApplicationAdapter = DS.RESTAdapter.extend({
namespace: 'api'
});
The Ember model:
App.Article = DS.Model.extend({
title: DS.attr('string'),
desc: DS.attr('string')
});
The route looks like this:
App.MainRoute = Ember.Route.extend({
model: function() {
console.log(this.store.find('article')); // isRejected: true, reason: Object has no method 'eachTransformedAttribute'
this.store.find('article').then(function(results){console.log(results)}); //nothing
}
});
Here is the data:
{
"articles": [{
"_id": "5266057ee074693175000001",
"__v": 0,
"createdAt": "2013-10-22T04:56:30.631Z",
"desc": "testing, testing",
"title": "Basic",
"id": "5266057ee074693175000001"
}, {
"_id": "5266057ee074693175000002",
"__v": 0,
"createdAt": "2013-10-22T04:56:30.636Z",
"desc": "testing, testing",
"title": "Basic2",
"id": "5266057ee074693175000002"
}, {
"_id": "5266057ee074693175000003",
"__v": 0,
"createdAt": "2013-10-22T04:56:30.636Z",
"desc": "testing, testing",
"title": "Basic3",
"id": "5266057ee074693175000003"
}, {
"_id": "5266057ee074693175000004",
"__v": 0,
"createdAt": "2013-10-22T04:56:30.636Z",
"desc": "testing, testing",
"title": "Basic4",
"id": "5266057ee074693175000004"
}]
}
I am using ember-tools to manage the project build.
The issue is with ember-tools default build placing the Model definition after the Route.
UPDATED: This is because I manually created the Article model without using a generator. (I've since used the generator and the order is created correctly)
I've fixed it by manually updated the built: application.js from this:
App.MainRoute = Ember.Route.extend({
model: function() {
return this.store.find('document');
}
});
App.Article = DS.Model.extend({
title: DS.attr('string'),
file: DS.attr('string')
});
to this:
App.Article = DS.Model.extend({
title: DS.attr('string'),
file: DS.attr('string')
});
App.MainRoute = Ember.Route.extend({
model: function() {
return this.store.find('document');
}
});
I resolved this by inspecting a working app, and found that within the JSONSerializer applyTransforms() type was referencing a different type:
It should be the namespace model Class like this:

error when upgrading to ember-data beta2

I'm getting this error when trying to load a set of records through a restful api. It works with ember-model but when I switch to ember-data (beta 2) and ember.js (1.0), I get this error.
Assertion failed: No model was found for '0'
App.ApplicationAdapter = DS.RESTAdapter.extend({
host: 'http://localhost:8080',
namespace: 'api'
});
App.Router.map(function() {
this.resource('about');
this.resource('pages', function() {
this.resource('page', { path: ':page_id' });
});
this.resource('login');
});
App.AuthenticatedRoute = Ember.Route.extend({
actions: {
error: function(reason, transition) {
if (reason.status == 403) {
alert('You must login');
this.transitionTo('login');
}
else {
//alert('non 403 error:'+reason.status);
this.transitionTo('login');
}
}
}
});
App.PagesRoute = Ember.Route.extend({
model: function() {
return this.store.find('page');
}
});
App.PageRoute = Ember.Route.extend({
model: function(params) {
return this.store.find('page', params.page_id);
}
});
App.Page = DS.Model.extend({
user: DS.attr('string'),
slug: DS.attr('string'),
zcontent: DS.attr(),
title: DS.attr('string'),
create_time: DS.attr('date'),
update_time: DS.attr('date')
});
Here is what the backend returned:
{
"pages": [
{
"update_time": "2013-01-14 19:59:35.744855",
"title": "",
"id": 38,
"create_time": "2012-08-04 15:08:16",
"user": "robert-jones",
"slug": "orange"
},
{
"update_time": "2013-01-14 19:59:35.899830",
"title": "",
"id": 47,
"create_time": "2012-08-03 10:04:07",
"user": "robert-jones",
"slug": "REVIEWStheraputics"
},
{
"update_time": "2012-12-18 07:16:13.656509",
"title": "'Notes on Temperature Heat Map'",
"id": 17,
"create_time": "2012-12-18 07:14:48.118119",
"user": "robert-jones",
"slug": "50612c27b94ca650"
},
{
"update_time": "2012-12-12 19:48:08.079021",
"title": "'Notes on Dyanmic Heat Map'",
"id": 8,
"create_time": "2012-12-12 19:48:08.013336",
"user": "robert-jones",
"slug": "c5642b4c14d901cf"
}
]
}
I've run into this before when my server was just returning a raw array instead of an object with a root element. That is, instead of this:
{pages : [...]}
I was accidentally returning this:
[...]
Kind of hard to say without a JSBin to look at.

How to use belongsTo in ember-model?

I have created FIXTURES using ember-model, but i am not able to use following node on template
"logged_in": {
"id" : "1",
"logged": true,
"username": "sac1245",
"account_id": "4214"
}
I have implemented belongsTo relation for this node but it throwing one error : Uncaught Error: Ember.Adapter must implement findQuery
Here i have listed my model code :
Astcart.Application = Ember.Model.extend({
name: Ember.attr(),
logo_url : Ember.attr(),
list: Ember.hasMany('Astcart.List', {key: 'list', embedded: true}),
logged_in: Ember.belongsTo('Astcart.Logged_in', {key: 'logged_in'})
});
Astcart.List = Ember.Model.extend({
name: Ember.attr()
});
Astcart.Logged_in = Ember.Model.extend({
id: Ember.attr(),
logged: Ember.attr(),
username: Ember.attr(),
account_id: Ember.attr()
});
Astcart.Application.adapter = Ember.FixtureAdapter.create();
Astcart.Application.FIXTURES = [
{
"id" : "1",
"logo_url": "img/logo.jpg",
"logged_in": {
"id" : "1",
"logged": true,
"username": "sac1245",
"account_id": "4214"
},
"name": "gau",
"list": [
{
"id" : "1",
"name": "amit"
},
{
"id" : "2",
"name": "amit1"
}
]
}
];
Template code :
{{#each item in model}}
{{item.name}}
{{item.logged_in.logged}}
{{/each}}
Router code :
Astcart.ApplicationRoute = Ember.Route.extend({
model: function() {
return Astcart.Application.find();
}
});
Can any one show me how to access data of above node in template?
Your current fixture have the logged_in data embedded:
Astcart.Application.FIXTURES=[
{
...
"logged_in": {
"id": "1",
"logged": true,
"username": "sac1245",
"account_id": "4214"
},
...
}
];
So the logged_in property mapping need the parameter embedded: true, to be able to find this data, as follow:
Astcart.Application = Ember.Model.extend({
...
logged_in: Ember.belongsTo('Astcart.Logged_in', {key: 'logged_in', embedded: true })
});
Without this it will try to query for the Astcart.Logged_in:
Astcart.Logged_in.find(1)
and because it doesn't have an adapter, will fail with the exception: Uncaught Error: Ember.Adapter must implement findQuery
You can see this working in that fiddle http://jsfiddle.net/marciojunior/8zjsh/

Trouble consuming json rest data in ember-data

I'm trying to parse a json dataset in my ember data models but this throws an error in het console:
Uncaught TypeError: Cannot call method '_create' of undefined
DS.Store.Ember.Object.extend.materializeRecord
DS.Store.Ember.Object.extend.findByClientId
What am I doing wrong here?
This is the data I receive from the server:
{
"newsitems": [
{
"date": "2013-02-10T15:00:00+01:00",
"id": "1",
"images": [
{
"id": "1",
"value": "image.JPG"
},
{
"id": "3",
"value": "anotherimage.jpg"
}
],
"slug": "some-slug",
"summary": "some summary",
"text": "some text",
"thumb": {
"id": "2",
"value": "someimage.JPG"
},
"title": "Some title",
"type": "1",
"videos": [
{
"id": "AEOpX8tmiUI",
"value": "AEOpX8tmiUI"
},
{
"id": "kxopViU98Xo",
"value": "kxopViU98Xo"
}
]
}
]
}
These are my models:
App.NewsitemThumb = DS.Model.extend({
value: DS.attr('string'),
newsitem: DS.belongsTo('App.Newsitem')
});
App.NewsitemImage = DS.Model.extend({
value: DS.attr('string'),
newsitem: DS.belongsTo('App.Newsitem')
});
App.NewsitemVideo = DS.Model.extend({
value: DS.attr('string'),
newsitem: DS.belongsTo('App.Newsitem')
});
App.Newsitem = DS.Model.extend({
slug: DS.attr('string'),
type: DS.attr('string'),
title: DS.attr('string'),
summary: DS.attr('string'),
text: DS.attr('string'),
date: DS.attr('date'),
thumb: DS.belongsTo('App.NewsitemThumb'),
images: DS.hasMany('App.NewsitemImage'),
videos: DS.hasMany('App.NewsitemVideo')
});
For the record, any suggestions for optimizing these models are welcome. It feels so weird to make 3 models for video, images and a thumb.
According to this issue, this error pops up when you don't specify an explicit mapping for a hasMany relationship in your adapter.
Try defining your store as
App.Store = DS.Store.extend({
revision: 11,
adapter: DS.RESTAdapter.extend({
serializer: DS.RESTSerializer.extend({
init: function() {
this._super();
this.map("App.Newsitem", {
images: { embedded: "load" },
videos: { embedded: "load" }
});
}
})
})
});