I have some models with similar names:
issue-statuse.js
issue-type.js
issue-type is working perfectly, but issue-statuse is causing trouble:
WARNING: Encountered "issue_statuses" in payload, but no model was found for model name "issue-status" (resolved model name using soporte#serializer:issue-statuse:.modelNameFromPayloadKey("issue_statuses"))
//<!--app/adapters/application.js-->
import Ember from 'ember';
import DS from 'ember-data';
export default DS.RESTAdapter.extend({
namespace: 'api/v1',
host: 'http://127.0.0.1:3000',
coalesceFindRequests: true,
headers: {
withCredentials: true,
Authorization: 'Basic eG9qbzpzZWNyZXQ=',
crossDomain: true
},
pathForType: function(type) {
return Ember.String.underscore(type)+'s';
}
});
// added a 's' for pluralize names, as when we need in underscore are in singular once again ...
//<!--app/models/issue-statuse.js-->
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
short: DS.attr('string'),
plural: DS.attr('string'),
created_at: DS.attr('date'),
active: DS.attr('boolean')
});
I have a workaround in a Serializer, I don't like it but with it it's working fine:
//<<!--app/serializers/issue-statuse.js
import DS from 'ember-data';
export default DS.RESTSerializer.extend({
modelNameFromPayloadKey: function(payloadKey) {
if (payloadKey === 'issue_statuses') {
return this._super("issue-statuse"); //this._super(payloadKey.replace('blog/', ''));
} else {
return this._super('issue-statuse'); //this._super(payloadKey);
}
}
});
But if I use this Serializer, I've got a Deprecation Warning:
Your custom serializer uses the old version of the Serializer API, with `extract` hooks. Please upgrade your serializers to the new Serializer API using `normalizeResponse` hooks instead.
So, I have two options, first one is try to solve why Ember is not finding my model, and the second, use the serializer and try to understand the deprecation and how to eliminate it.
I would prefer option one :-)
Thanks,
edit
It was a typo here in the name of the model file, it's singular:
//<!--app/models/issue-statuse.js-->
edit 2
I've removed completely the app/serializers/issue-statuse.js and created an initializer with the inflector:
//<!--/app/initializers/inflector.js-->
import Ember from 'ember';
export function initialize(/* container, application */) {
var inflector = Ember.Inflector.inflector;
inflector.uncountable('aamc-pcrs');
inflector.irregular('issue-statuse', 'issue-statuses');
}
export default {
name: 'inflector',
initialize: initialize
};
edit 3
I'm using the
pathForType: function(type) {
return Ember.String.underscore(type)+'s';
},
in the Adaptor for changing - for _
My Backend API wants issue_statuses instead of issue-statuses for example. Maybe I can just rename the table in the inflector and remove also this line ...
Related
My ember app is not sending my foreign key to the back-end.
I have a table called issues which is has a related table called categories
My model is:
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
category_id: DS.belongsTo('category'),
description: DS.attr('string')
});
My route is:
import Ember from 'ember';
export default Ember.Route.extend({
model: function(){
return this.store.findAll('issue');
},
actions: {
create: function(){
var issue = this.store.createRecord('issue');
issue.name = this.get('controller').get('newName');
issue.description = this.get('controller').get('newDescription');
issue.category_id = parseInt(this.get('controller').get('newCategory'));
//debugger;
console.log(issue);
issue.save();
},
...
other actions
...
}
}
});
the console.log from above looks like the category_id is getting set correctly:
category_id: 3
description: "foobar"
name: "test"
However my JSON payload that gets sent to the backend looks like:
{"issue":{"name":"test","description":"foobar","category_id":null}}
I tried stepping through by adding a custom serialiser in app/serializers/application.js
export default DS.RESTSerializer.extend({
...
serialize: function(snapshot,options){
console.debug('options='+options);
debugger;
var json = this._super(snapshot, options);;
return json;
}
...
});
But I got lost in all the super calling super indirection.
The snapshot.record has category_id: 3, but the json coming back from the this._super() call has category_id: null
options has includeID:true
Any clues will be much appreciated ...
Ember : 2.0.2
Ember Data : 2.0.0
Your model definition is wrong, when dealing with relationships you define them just as you would define any other attribute, there is no need to use _id.
export default DS.Model.extend({
name: DS.attr('string'),
category: DS.belongsTo('category'),
description: DS.attr('string')
});
As for the creation you should always use setters/getters when dealing with ember objects:
create: function() {
var issue = this.store.createRecord('issue', {
name: this.get('controller').get('newName'),
description: this.get('controller').get('newDescription'),
category: this.get('controller').get('newCategory') // assuming new category is a DS.Model instance of category
});
issue.save();
}
If you wish to stick to the syntax you have you would use issue.set('name', this.get('controller').get('newName')), from the looks of your code it seems you are going about this in the wrong way.
You should have a this.route('new') nested under your issues route, that way you wouldn't have to use the controller to store information.
You would simply set the model of the new route to:
model: function() {
return this.store.createRecord('issue');
}
Your template would make use of the input helpers like so:
{{input value=model.name}} and your action would just get the currentModel and call .save().
If I have a field that is in snake case coming back from the api, how should I define that field in the model? Im using the JSONAPIAdapter. It seems like fields that is one word work fine, but snake case fields come back as undefined.
This is how I have it defined in my model:
import DS from 'ember-data';
export default DS.Model.extend({
typecode_desc: DS.attr('string'),
contactnum: DS.attr('string'),
email: DS.attr('number'),
individual: DS.belongsTo('individual', {async: false})
});
And this is how the json comes back from the API:
1: {
id: "96"
type: "contact_infos"
attributes: {
typecode_desc: "E-mail address"
contactnum: "billybear#yahoo.com"
email: 1
}
}
However, in the ember inspector, typecode_desc comes back as being undefined. Is there something I need to do to tell ember that fields will come back as being snake case?
You need to define keyForRelationship in your JSON API serializer. It will look something like this:
import DS from 'ember-data';
import Ember from 'ember';
export default DS.JSONAPISerializer.extend({
keyForAttribute: function(attr) {
return Ember.String.underscore(attr);
},
keyForRelationship: function(attr) {
return Ember.String.underscore(attr);
}
});
In an ember 1.13.3 app, I have this route :
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return this.store.find('skill');
}
});
And this model :
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
description: DS.attr('string'),
link: DS.attr('string'),
acquired_skills: DS.hasMany('users', { async: true, inverse: 'acquired_skills' } ),
searched_skills: DS.hasMany('users', { async: true, inverse: 'searched_skills' } )
});
This is the result returned by the api :
{"skills":[{"id":1,"name":"Ember","description":"JS Framework","link":null}]}
The array is empty. I can check it with this console.log(this.store.find('skill').get('length')); and I have 0.
What's wrong?
store.find() is an asynchronous operation. It returns a promise. To access the actual data you have to pass a callback to the promise. When the data is fetched from the backend, the promise resolves and executes the callback, passing the data into it:
var foo = this.store.find('skill');
console.log("typeof foo", typeof foo);
foo.then( function(result) {
console.log("result", result);
});
console.log("end of script");
The above code would produce the following output:
typeof foo, Promise
end of script
result, Object
UPD 1
You're using a JSONAPIAdapter. The payload you've shown does not comply with the JSON API spec. You should update your backend to conform to the spec.
If you can't, use the RESTAdapter and RESTSerializer as a workaround:
app/adapters/application.js
import DS from 'ember-data';
export default DS.RESTAdapter.extend({
host: 'http://localhost:3000',
namespace: 'api/v1'
});
app/serializers/application.js
import DS from 'ember-data';
export default DS.RESTSerializer.extend({
isNewSerializerAPI: false
});
More info here: http://emberjs.com/blog/2015/06/18/ember-data-1-13-released.html
I recently started learning Ember and using Ember-CLI so I'm not quite well educated about Ember Data and what array names it expects for relationships that are in sub directories in my app.
// models/server.js
import DS from 'ember-data';
export default DS.Model.extend({
serverHistory: DS.hasMany("history/server", { async: true })
});
// models/history/server.js
import DS from 'ember-data';
export default DS.Model.extend({
server: DS.belongsTo("server", { async: true })
});
I've tried returning these names from my API
server_historys_ids
server_histories_ids
history_server_ids
history_servers_ids
But I don't see an XHR request for Server history in my application. The servers itself are fetched fine.
Update
I changed my relationship name and the API is returning history ids but I'm still not getting an history json request even though I'm trying to each in the template. The game relationship data is accessible in the template and a request is successfully made.
// models/server.js
import DS from 'ember-data';
export default DS.Model.extend({
// attr's here.. not relevant
// Relationships
game: DS.belongsTo("game", { async: true }), // works
serverHistories: DS.hasMany("history/server", { async: true }) // doesn't make a request like game does.
});
I also have an adapter/history/server.js but it's only telling what namespace to use - "api".
Update 2
I think the problem may be in the way I'm calling the data to the model.
// routes/server/view/index.js
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
var parentModel = this.modelFor("server.view");
return this.store.query("server", { server_address: parentModel.server_address });
// return this.store.find("server", 1);
}
});
How come when I use find with an id it updates the template data and when I use query with parameters it doesn't?
Update 3
So I got my find and query problem sorted out, here's the way I got it to work: https://stackoverflow.com/a/31831667/1814027
The relationship problem still persists. I see no serverHistory data in my Ember toolbar nor a request being made to the API for it.
I beleive serverHistory is anti-conventional name for hasMany and serverHistories should be instead.
export default DS.Model.extend({
serverHistories: DS.hasMany("history/server", { async: true })
});
Then in case of ActiveModelAdapter expected server payload is:
{"server": {"id": 1, "server_history_ids": [1,2,3]}}
It doesn't depend on the fact that serverHistory is namespaced model, it depends on relation name only.
For example for model:
// models/server.js
import DS from 'ember-data';
export default DS.Model.extend({
bars: DS.hasMany("history/server", { async: true })
});
expected payload is:
{"server": {"id": 1, "bar_ids": [1,2,3]}}
Update
Working ember-cli example: https://github.com/artych/so_ember_data_subdir
Artych's answer helped me on the right path but Ember didn't want to recognise server_history_ids so I just renamed the hasMany relation to histories and returned histories: [] from my API. Now it works.. don't know why but it works.
I'm getting the following error while using DS.EmbeddedRecordsMixin when my records have embedded data:
TypeError: Cannot read property 'typeKey' of undefined
I'm using Ember CLI 0.1.2 with Ember 1.7.0 and Ember Data 1.0.0#beta11
My adapters:
Application Adapter - /app/adapters/application.js (RestAdapter):
import DS from 'ember-data';
import config from '../config/environment';
export default DS.RESTAdapter.extend({
namespace: config.APP.RestAdapterNamespace,
host: config.APP.SERVER_LOCATION
});
Adapter in question - /app/adapters/screen.js (screenSlideGroups should be embedded):
import ApplicationAdapter from './application';
import DS from 'ember-data';
export default ApplicationAdapter.extend(DS.EmbeddedRecordsMixin, {
attrs: {
screenSlideGroups: { embedded: 'always' }
}
});
Model: /app/models/screen.js
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
path: DS.attr('string'),
screenSlideGroups: DS.hasMany('screen-slide-group')
});
Example of data returned from the API:
{
"screen":[
{
"id":1,
"name":"Weather",
"path":"weather",
"screenSlideGroups":[
{
"id":1,
"screen":1,
"slideGroup":1,
"order":1
}
],
"lastUpdated":"2014-09-18T18:26:25.69"
},
{
"id":2,
"name":"Front Lobby",
"path":"frontlobby",
"screenSlideGroups":[
],
"lastUpdated":"0001-01-01T00:00:00"
}
]
}
I also tried removing screen from the embedded record, incase the backwards reference could screw it up, but it didn't make a difference. As far as I can tell, the EmbeddedRecordsMixin adapter I created may not be getting used at all.
Any ideas on what may have gone wrong here?
Turns out I misread the documentation, and DS.EmbeddedRecordsMixin should be on the Serializer, NOT the Adapter.
The correct implementation was as follows:
/app/serializers/screen.js:
import DS from 'ember-data';
export default DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
screenSlideGroups: { embedded: 'always' }
}
});