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')
})))