I have a Rest adapter right configured and when I try:
router.js
export default Ember.Route.extend({
model: function() {
return this.store.find('main.user');
}
});
I got this:
WARNING: Encountered "main.user" in payload, but no model was found
for model name "mainUser" (resolved model name using
plezure#serializer:-rest:.typeForRoot("main.user"))
Error while processing route:
main.user Assertion Failed: The response from a findAll must be an
Array, not undefined Error: Assertion Failed: The response from a
findAll must be an Array, not undefined
My Json return:
{
"main.user": [
{ "id": "1", "name": "foo" },
{ "id": "2", "name": "bar" }
]
}
model.js
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string')
});
My pod are right configured, everything is fine, all works if I change to the find to a non-pod model, like this (model exists at main/):
export default Ember.Route.extend({
model: function() {
return this.store.find('main');
}
});
But with 'main.user' ember is uncapable to deal with json return, using fixtures pod names works well, it's ony happens on json response.
Anyone have any ideia about this kind of issue?
Related
My Backend Rails API consumes POST requests in the form of
{
"name": "Mark White",
"email" : "mark#xyz.com"
}
Have tried this in Postman and this creates a record successfully.
In my ember frontend, Im using the following code to create a new record, from a form input:
app/routes/addUser.js
import Ember from 'ember';
export default Ember.Route.extend({
actions: {
addUser(){
let formData = {
"name": this.controller.get('name'),
"email": this.controller.get('email')
};
let newUser = this.store.createRecord('user',formData);
newUser.save();
}
}
});
which generates the request as
{
"user": {
"name": "Mark White",
"email" : "mark#xyz.com"
}
}
which my backend is not prepared to handle and throws an error.
Any way I can quickly conform to the json format that works for me in Postman.
When the question is along the lines with the "How can I change my payload to server for it to be in a certain format?" then you should have a look at customizing a serializer.
But it looks like for solving your problem you might wanna take the standard JSON Serializer; in your app/serializers/application.js just type the following:
import JSONSerializer from '#ember-data/serializer/json';
export default class ApplicationSerializer extends JSONSerializer {
// ...
}
Note that it's for the Ember.js v4, according to your example you're using a bit older version so just adjust the syntax accordingly.
I'm using the latest version of EmberJS and Ember Data.
I have the next JSON data:
[{
"id": 6,
"name": "First object",
"vol": 40,
"description": "bla bla bla",
"category": "first"
}, {
"id": 7,
"name": "Second object",
"vol": 17,
"description": "Some description",
"category": "second"
}]
And the next model:
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
vol: DS.attr('number'),
description: DS.attr('string'),
category: DS.attr('string')
});
And I don't understand how to make Ember data works. I have suspicious that ember data expects something like next:
[{
model-name {
"id": 6,
"name": "First object",
"vol": 40,
"description": "bla bla bla",
"category": "first"
}
}, {
model-name {
"id": 7,
"name": "Second object",
"vol": 17,
"description": "Some description",
"category": "second"
}
}]
In console I have a bunch of warnings:
WARNING: Encountered "0" in payload, but no model was found for model
name "0" (resolved model name using emdber-drink-
it#serializer:application:.modelNameFromPayloadKey("0"))
WARNING: Encountered "1" in payload, but no model was found for model
name "1" (resolved model name using emdber-drink-
it#serializer:application:.modelNameFromPayloadKey("1"))
And more than hundred similar records (that is how many records server returns on request).
And no data in store.
How can I fix this problem without changing JSON that I receive from server?
From http://emberjs.com/api/data/classes/DS.JSONSerializer.html
In Ember Data a Serializer is used to serialize and deserialize
records when they are transferred in and out of an external source.
This process involves normalizing property names, transforming
attribute values and serializing relationships.
At this time there are 4 types of serializers:
DS.Serializer
DS.JSONSerializer
DS.RESTSerializer
DS.JSONAPISerializer
The JSON data you have is plain json.
JSONSerializer is useful for simpler or legacy backends that may not
support the http://jsonapi.org/ spec
So you need JSONSerializer which is the most simple solution to consume plain json data.
With ember-cli is pretty easy create a new serializer, for example for a model book:
ember generate serializer book
which will produce something like this:
version: 1.13.8
installing serializer
create app/serializers/book.js
installing serializer-test
create tests/unit/serializers/book-test.js
The previous command will create a serializer of type RESTSerializer. (If you dont use ember -cli just create this file at hand)
// app/serializers/book.js
import DS from 'ember-data';
export default DS.RESTSerializer.extend({
});
and then change RESTSerializer by JSONSerializer:
import DS from 'ember-data';
export default DS.JSONSerializer.extend({
primaryKey: '_id', // useful for mongodb-like data
});
I hope you enjoy learning ember as much as I do.
You should be able to add a custom serializer to add a root key to your JSON data. I haven't tested this but you could try something like:
(using a "book" model as an example)
// app/serializers/book.js
import DS from 'ember-data';
export default DS.RESTSerializer.extend({
extractArray: function(store, type, payload) {
var newPayload = {};
newPayload[type.modelName] = payload;
return this._super(store, type, newPayload);
}
});
If this is a problem with the entire API, then you might need to make a custom serializer for the entire application and use the passed-in type argument to build the root keys.
Also as a side note, I probably wouldn't use Ember Data if I didn't have control over the API. Unless it follows strict guidelines like jsonapi.org, you're bound to have a few headaches with it.
EDIT - changed answer to the suggestion above (using 'type' to build root key).
I took another approach and overloaded the 'modelNameFromPayloadKey' method.
If the payload key is of type integer, it will be mapped to the name of the model instead.
// app/serializers/<model>.js
import DS from 'ember-data';
import normalizeModelName from "ember-data/-private/system/normalize-model-name";
import {singularize} from "ember-inflector";
export default DS.RESTSerializer.extend({
model: '<model>',
modelNameFromPayloadKey(key) {
// Check whether the key is of type integer
if (!isNaN(key)) {
return normalizeModelName(this.get('model'));
}
return singularize(normalizeModelName(key));
},
});
DEBUG: Ember : 1.8.1
ember.js:15373DEBUG: Ember Data : 1.0.0-beta.18
ember.js:15373DEBUG: Handlebars : 1.3.0
ember.js:15373DEBUG: jQuery : 1.11.3
So I have a "Request" model which can depend on an account or other Requests that stand in for and account when it is fulfilled.
I'm a bit confused about how to get the JSON right for Ember to pick this up.
On the server-side, ActiveModelSeriailzers seems to want to serialize polymorphic relationships like this:
{
"id" : 1,
"account_id" : { "id": 1, "type": "account"}
}
I have the following ED Models:
// abstract-account.js
export default DS.Model.extend();
//account.js
export default AbstractAccount.extend();
//request.js
export default DS.Model.extend({
account: DS.belongsTo('abstractAccount', { polymorphic: true} )
});
When I try to load the record using the default json, I get
Error: Assertion Failed: You must include an `id` for account in an object passed to `push`
In my reading, I had gotten the impression that belongsTo polymorphic assocaitions should get sent like:
{
"id" : 1,
"account_id" : 1,
"account_type" : "Account"
}
If I change the server to serialize like that, I instead get
Uncaught Error: Assertion Failed: You may not pass `null` as id to the store's find method
I'm not really sure what I'm missing,or what the current recommended practice is.
I am using a similar setup with the first convention. Keep in mind Ember expects JSON objects to be namespaced under the class name, so for a GET to /requests you would need to return something like
{
'requests': [
{
'id': 1,
'account': { id: 10, type: 'account' }
},
{
'id': 2,
'account': { id: 20, type: 'some_other_abstract_account' }
}
]
}
This is with the RESTAdapter declared in application/adapter.js, I haven't tried the ActiveModelAdapter. I have seen documents advising another convention, but it's working for me with ember data 1.0.0-beta.16
I'm working on a project using Ember/Ember-Data and there is a related/already existing service which is provide API with JSON response.
My project must interact with that service, but the response from that API is someting like below:
{ "id": 39402, "name": "My Name" }
or
[ {"id": 38492, "name": "Other Name" } ]
there is no person: or persons: that is required by Ember-Data compatable response.
How can I using this response on Ember-Data without change on the service or without build API gateway?
Ember-Data uses DS.RestAdapter, which in turn uses DS.RESTSerializer which extends from DS.JSONSerializer for serializing, extracting and massaging data that comes in from the server.
Since in your case you already have the data in your payload, all you need to do for reading the data is override extract method in the JSONSerializer which is actually quite simple.
If you are using ember-cli (which you should :)), your person.js file located inside your app/serializers directory would look as follows.
import DS from 'ember-data';
export default DS.JSONSerializer.extend({
extract: function(store, primaryType, payload) {
return payload;
}
});
If you are not using ember-cli, you can do the following:
App.PersonSerializer = DS.JSONSerializer.extend({
extract: function(store, primaryType, payload) {
return payload;
}
});
I've been banging my head against deserializing data with Ember. I feel like I've set it up right but I keep getting the same error. I'm trying to use the EmbeddedRecords Mixin, but it simply hasn't worked for me. Below is my debug data.
DEBUG: Ember : 1.6.1
DEBUG: Ember Data : 1.0.0-beta.7+canary.b45e23ba
DEBUG: Handlebars : 1.3.0
DEBUG: jQuery : 1.10.2
DEBUG: Model Fragments : 0.2.2
Here is a simple setup of what I've been doing. I have my model defined like this -
App.Subject = DS.Model.extend({
title: DS.attr('string'),
sections: DS.hasMany('section')
});
App.Section = DS.Model.extend({
title: DS.attr('string'),
subject: DS.belongsTo('subject')
});
App.SubjectSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
sections: { embedded: 'always' }
}
});
and here is the format of the JSON payload I'm sending for a 'show'
{
"subject": {
"_id":"549987b098909eef0ac2d691",
"title":"Maths",
"sections":[{
"title":"Precalc",
"_id":"549987b098909eef0ac2d693"
}, {
"title":"Calc",
"_id":"549987b098909eef0ac2d692"
}],"__v":0
}
}
I get the errors in the console
Error while processing route: subjects.show undefined is not a function TypeError: undefined is not a function
at Ember.Mixin.create.extractSingle (http://localhost:3300/js/highered.js:2043:25)
at apply (http://localhost:3300/js/highered.js:20664:27)
at superWrapper [as extractSingle] (http://localhost:3300/js/highered.js:20240:15)
at Ember.Object.extend.extractFind (http://localhost:3300/js/highered.js:4007:21)
at Ember.Object.extend.extract (http://localhost:3300/js/highered.js:3892:37)
at http://localhost:3300/js/highered.js:11864:34
at invokeCallback (http://localhost:3300/js/highered.js:23228:19)
at publish (http://localhost:3300/js/highered.js:22898:9)
at publishFulfillment (http://localhost:3300/js/highered.js:23318:7)
at http://localhost:3300/js/highered.js:28736:9
highered.js:16581 undefined is not a function TypeError: undefined is not a function
at Ember.Mixin.create.extractSingle (http://localhost:3300/js/highered.js:2043:25)
at apply (http://localhost:3300/js/highered.js:20664:27)
at superWrapper [as extractSingle] (http://localhost:3300/js/highered.js:20240:15)
at Ember.Object.extend.extractFind (http://localhost:3300/js/highered.js:4007:21)
at Ember.Object.extend.extract (http://localhost:3300/js/highered.js:3892:37)
at http://localhost:3300/js/highered.js:11864:34
at invokeCallback (http://localhost:3300/js/highered.js:23228:19)
at publish (http://localhost:3300/js/highered.js:22898:9)
at publishFulfillment (http://localhost:3300/js/highered.js:23318:7)
at http://localhost:3300/js/highered.js:28736:9
Which as best I can tell is directly related to extractSingle at the this.keyForAttribute method
extractSingle: function(store, primaryType, payload, recordId, requestType) {
var root = this.keyForAttribute(primaryType.typeKey),
partial = payload[root];
updatePayloadWithEmbedded(store, this, primaryType, partial, payload);
return this._super(store, primaryType, payload, recordId, requestType);
},
although an interesting thing to note is that the error occurs at extractArray when I am using the subjects index route, which return the json above but with array brackets as well.
extractArray: function(store, type, payload) {
var root = this.keyForAttribute(type.typeKey),
partials = payload[pluralize(root)];
forEach(partials, function(partial) {
updatePayloadWithEmbedded(store, this, type, partial, payload);
}, this);
return this._super(store, type, payload);
}
Which makes me think that Ember Data is having trouble recognizing the format. This happens any time I define a serializer for a model, not just when I enable embedded records.
I'm hoping someone will be able to explain this. As a final note I've been using the Ember Data Model Fragments library as well, but I disabled that and still got this error so I don't think that is it.
The Embedded Records mixin doesn't work with the RESTSerializer before beta 9.
You can view the state of it here Ember-data embedded records current state?
You'll also want to be wary of updating ember or ember data without the other version in certain circumstances. Ember Data cannot read property 'async' of undefined