Ember data sideloaded mockjax call - ember.js

I try to model an ajax call via mockjax for ember data.
my models:
App.Service = DS.Model.extend({
name: DS.attr('string'),
service_prices: DS.hasMany('servicePrice')
});
App.ServicePrice = DS.Model.extend({
unit_price: DS.attr('number'),
qty_unit: DS.belongsTo('qtyUnit'),
service: DS.belongsTo('service')
});
App.QtyUnit = DS.Model.extend(Ember.Validations.Mixin, {
name: DS.attr('string'),
});
App.Order = DS.Model.extend({
service: DS.belongsTo('service'),
qty_unit:DS.belongsTo('qtyUnit'),
});
I try to load an order record via mockjax. (Push the button.) According to the console after the call
MOCK GET: /orders/1
Object {url: "/orders/1", type: "GET", isLocal: false, global: true, processData: true…}
Ember data tries a 2nd call
GET http://run.jsbin.com/services/%3CApp.Service:ember518:1%3E 404 (Not Found)
First of all i dont understend why is the 2nd call? Service is sideloaded in my order JSON
var order = {
"order" : {"id":1,"service":1,"qty_unit":4},
"service":[{"id":1,"name":"ENG-GER","service_prices":[1,2]}],
"servicePrices":[
{"id":1,"qty_unit":4,"unit_price":3},
{"id":2,"qty_unit":5,"unit_price":4}
],
"qtyUnits":[
{"id":4,"name":"character"},
{"id":5,"name":"word"},
{"id":6,"name":"sentence"}
]
};
And why tries ember-data call the record App.Service:ember518:1 instead of its id "1"?
Here is the JsBin
http://jsbin.com/finahuna/1/edit

The problem was your setQtyUnits method. You were passing service model rather than just id as expected by your mock endpoint. ember518 is the ember generated name of service model instance in this case which was getting passed rather than id. Modified method is -
setQtyUnits:function(){
var service_id = this.get('model.order.service.id');
if (service_id !== null)
{
var self = this;
//find returns a promise
this.store.find('service',service_id).then(function(service){
//on success
var servicePrices = service.get('service_prices');
var qtyUnits = servicePrices.mapBy('qty_unit');
console.log(qtyUnits);
self.set('qtyUnits', qtyUnits);
});
} else {
this.set('qtyUnits', null);
}
}.observes('model.order.service')
Here is the modified bin - http://jsbin.com/finahuna/4/edit

Related

ember data not saving foreign key, sent as null

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().

Emberjs - Custom Adapter

I'm quit new into the world of the Adapter in Ember, and I would like to create a custom one to save some data into the webSQL database for the compatible browser.
It might look very simple but I'm stuck at the beginning of this process.
I have this in a separate file :
DS.WebSQLAdapter = DS.Adapter.extend({
dbName: 'testDb',
dbVersion: '1.0',
dbDisplayName: 'Test Db',
dbSize: (2 * 1024 * 1024),
init: function() {
this.db = cont.openDatabase( this.dbName, this.dbVersion, this.dbDisplayName, this.dbSize );
},
createRecord: function( store, type, query, recordArray ) {
console.log(data);
}
})
In my app.js file :
window.App = Ember.Application.create({});
App.ApplicationAdapter = DS.WebSQLAdapter;
And when I do this in my controller :
App.ApplicationController = Ember.ArrayController.extend({
actions: {
myAction: function() {
this.store.createRecord('someDB', {key: 'test', title: 'myTitle'});
}
}
})
It says that it couldn't found the model someDB.. Do I need to create a model as well for my adapter even though I'm using websql to fetch the data ?
It's telling you that SomeDB doesn't exist. Ember is expecting the following to be in your code somewhere:
App.SomeDB = DS.Model.extend({});
If you don't declare a SomeDB model, you can't create a new record of that type. (At least not with the Ember-Data store.)

TypeError: Unable to set property 'store' of undefined or null reference in ember.js

Below is the code I am using to get data from web API. But every time I try to retrieve data I get same error: Unable to set property 'store' of undefined or null reference in ember.js.
/// <reference path="Lib/ember.js" />
/// <reference path="Lib/ember-data.js" />
var App = Ember.Application.create();
Ember.onerror = function(e) {
alert(e);
};
App.ApplicationAdapter = DS.RESTAdapter.extend({
namespace: 'api'
});
App.store = DS.Store.create({
adapter: App.ApplicationAdapter
});
App.Product = DS.Model.extend({
ID: DS.attr("int"),
Name: DS.attr('string'),
Category: DS.attr('string'),
});
App.ApplicationRoute = Ember.Route.extend({
model: function() {
{{debugger}}
var store1 = this.get("store")
var k = store1.find('product', 1)
return k;
}
});
Your problem is with the returned json from the server. You need to return the following object:
{
product: {
// key value
}
}
If you want to use the DS.RESTAdapter defaults, you can just return the data in that format:
{
product: {
id: 1,
name: 'some name',
category: 'some category'
}
}
And change your model mapping to:
App.Product = DS.Model.extend({
name: DS.attr('string'),
category: DS.attr('string'),
});
If you want to use the capitalized properties like Name, Category. You will need to override some methods of DS.RESTAdapter. If your endpoing doesn't match this format.
Other error is that doesn't exist a DS.attr('int') just DS.attr('number'). But you can remove the id mapping, since is created by default.
This is a jsfiddle with this working http://jsfiddle.net/marciojunior/W5LEH/
Ensure that you are using last versions of Ember.js and Ember-Data.
This is how you define a store for you application:
App.Store = DS.Store.extend({
adapter: App.ApplicationAdapter
});
Note the capital S in Store and extend instead of create.
See Ember-Data Guide

Ember js how to use the BasicAdapter

I am looking for a guide that will help me understand syncing models in ember. I tried to use the RestAdapter on the latest build and I am getting an error. So I decided to use the BasicAdapter based on stabilizing ember data on the ember js site.
Here is my model:
App.Accounts = DS.Model.extend({
name:DS.attr('string')
,date:DS.attr('date')
})
Here is where I declare the sync functions for the model.
App.Accounts.sync = {
list: function() {
$.ajax({
type: 'POST',
cache: false,
url: contextPath + 'account/list',
success: function(data) {
this.load()
},
error: function(jqXHR, textStatus, errorThrown) {
},
async: false
});
}
}
I am calling the list function in a setup controller:
App.TestRoute = Ember.Route.extend({
setupController:function(){
App.Accounts.list()
}
})
The function does not execute. What is the correct way to call sync functions in an ember application? Also, I could use a blog/article on this topic.
Thanks!
Have you checked out Ember Model it gives you a basic adapter without having to use EmberData.
Erik has a tutorial at embercasts.com you may need to signup to be beta user.
var attr = Ember.attr;
App.User = Ember.Model.extend({
id: attr(),
name: attr()
});
App.User.url = "/users";
App.User.adapter = Ember.RESTAdapter.create();
var newUser = App.User.create({name: "Erik"});
newUser.save(); // POST to /users.json
var existingUser = App.User.find(1); // GET /users/1.json
existingUser.set('name', 'Kris');
existingUser.get('isDirty'); // => true
existingUser.save(); // PUT /users/1.json
Cheers

Ember data find vs load

When you use findQuery in ember-data, does it also load the model localy ? I can't make the following code to work :
App.MyModel = DS.Model.extend {
name: DS.attr('string')
didLoad: ->
console.log('model loaded')
}
Now when I do something like :
objects = App.store.find(App.MyModel, [{name: "john"},{name: "jack"}])
The didLoad callback is not fired. When this callback is fired ?
To implement the query functionality you have to implement the findQuery method in your adapter. This method takes 4 arguments store, type, query, modelArray. When the server returns the data for the query, you have to invoke the load method on the modelArray to fill it with the query result. This method also loads the data into the store, see an example here: http://jsfiddle.net/pangratz666/5HMGd/.
App.store = DS.Store.create({
revision: 4,
adapter: DS.Adapter.create({
find: Ember.K,
findQuery: function(store, type, query, modelArray) {
// expect server to return this array
modelArray.load([{ id: 1, name: 'John'}, { id: 2, name: 'Jack'}]);
}
})
});
App.MyModel = DS.Model.extend({
name: DS.attr('string'),
didLoad: function() {
console.log('model loaded', this.toJSON());
}
});
// invoke query which loads the 2 models, and didLoad is called
App.store.find(App.MyModel, {});
​