Often times, you want to add some attributes to an Ember Data model dynamically (e.g. you might want a translateable attribute for each available locale). Lets say, you have a name attribute that you want to translate in English, Spanish, French and Chinese. Here’s how you would usually write it:
App.Product = DS.Model.extend({
nameEn: DS.attr('string'),
nameEs: DS.attr('string'),
nameFr: DS.attr('string'),
nameZh: DS.attr('string')
});
While this might be ok for a few locales, but consider doing this for a large number of locales. This is too much work!
Since, all we need to pass to DS.Model.extend is a JavaScript object, to support multiple attributes, all we need is to create the object dynamically based on the available locales before passing it on. Here’s a very simple function (using Combinatorics and _) that creates an object with propertyNameLocale : DS.attr(...)
pairs for each property and locale.
/**
* Creates an object with propertyNameLocale : DS.attr(...) for each property and locale
* @param properties
* @returns {*}
*/
translatedModelProperties: function (properties) {
return $.extend.apply($, _.flatten([
{},
Combinatorics.cartesianProduct(_.keys(properties), App.get('locales')).toArray().map(function (localePropertyNameArray) {
var propertyName = localePropertyNameArray[0];
return _.object([localePropertyNameArray.join('_').camelize()], [properties[propertyName]]);
})
]));
}
All you need now is to use it to super charge your models and you are done. No more duplication for every translatable property, Yay!
App.Product = DS.Model.extend($.extend({
// Non translated properties
price: DS.attr('number')
}, App.translatedModelProperties({
// Translatable properties
name: DS.attr('string')
})))