I'm creating a cocktail app with the models "cocktail", "membership", and "ingredient". The cocktail and ingredient models are pretty self explanatory and the membership model is for objects that link a cocktail to an ingredient with amount.
App.Cocktail = DS.Model.extend({
name: DS.attr('string'),
description: DS.attr('string'),
created_by: DS.attr('number'),
start_date: DS.attr('string'),
end_date: DS.attr('string'),
// link cocktail to memberships
membership: DS.hasMany('membership',{ async: true })
});
App.Membership = DS.Model.extend({
amount: DS.attr('string'),
// link membership to ingredient and cocktail
ingredient: DS.belongsTo('ingredient'),
cocktail: DS.belongsTo('cocktail')
});
App.Ingredient = DS.Model.extend({
name: DS.attr('string'),
description: DS.attr('string'),
start_date: DS.attr('string'),
end_date: DS.attr('string')
});
The problem I'm having is when I use ember-data to create a cocktail and then its memberships to ingredients the ingredient and cocktail ids for the REST call are strings not ints so the request body looks like this:
{membership:{amount:"2 litres",ingredient:"12",cocktail:"116"}}
when what I want instead:
{membership:{amount:"2 litres",ingredient:12,cocktail:116}}
Here's my code that performs the saving of which I'm pretty new to the idea of promises so not sure if this is structured in the most preferable way.
... code
actions: {
// fired when user presses save
submit: function() {
// some validation
var cocktailPromise = this._saveCocktail();
this._saveIngredientMemberships(cocktailPromise);
}
}
... more code
_saveCocktail: function() {
console.log('saving cocktail');
var cocktail = this.store.createRecord('cocktail', {
name: this.get('cocktailName'),
description: this.get('cocktailDescription'),
start_date: "now"
});
return cocktail.save();
},
_saveIngredientMemberships: function(cocktailPromise) {
console.log('saving cocktail ingredients');
// get the ingredients and amounts (memberships) the
// user entered and the store and set them as var here
// so they stay in scope.
var memberships = this.get('memberships');
var store = this.store;
// once cocktail is created
cocktailPromise.then(function(cocktail) {
console.log('cocktail ready, saving ingredients');
var membershipRecords = [];
for( var i = 0 ; i < memberships.length ; i++ ) {
membershipRecords[i] = store.createRecord('membership', {
cocktail: cocktail,
ingredient: memberships[i].get('ingredient'),
amount: memberships[i].get('amount')
});
membershipRecords[i].save();
}
}, function() {
console.log('something went wrong saving the cocktail!');
})
},
By default, Ember treats all IDs as strings (it coerces numbers to strings). What you'll want to do is override the RESTSerializer
. You can find all of the possible methods to override here. I would advise that you read the source code for the adapter as well. That will really help. It's been a while since I've used Ember-Data, but I believe the method you want to look at is serialize. I would do something like this:
App.ApplicationAdapter = DS.RESTAdapter.extend({
serialize: function(record, options) {
var json = this._super(record, options);
json.ingredient = parseInt(json.ingredient);
json.cocktail = parseInt(json.cocktail);
...
return json;
}
});
You can obviously make it more efficient for different models, but you get the idea. You might also be able to override a more specific method, which is why I recommended reading the source code too.