/* packages/mixins/lib/underscored_serializer_mixin.js */ (function(Ember, DS) { var get = Ember.get; var forEach = Ember.EnumerableUtils.forEach; /** @module ember-data @submodule mixins **/ /** The `UnderscoredSerializer` is intended use when creating a subclass of the DS.RESTSerializer. Based on `activemodel-adapter` package, supports `hasMany` and `belongsTo` records embedded in JSON payloads, designed to work out of the box with the [active_model_serializers](http://github.com/rails-api/active_model_serializers) Ruby gem. And is designed to integrate with an API that uses an underscored naming convention instead of camelCasing. @class DS.UnderscoredSerializer @constructor @namespace DS **/ DS.UnderscoredSerializer = Ember.Mixin.create({ // SERIALIZE /** Converts camelCased attributes to underscored when serializing. @method keyForAttribute @param {String} attribute @return String */ keyForAttribute: function(attr) { return Ember.String.decamelize(attr); }, /** Underscores relationship names and appends "_id" or "_ids" when serializing relationship keys. @method keyForRelationship @param {String} key @param {String} kind @return String */ keyForRelationship: function(key, kind) { key = Ember.String.decamelize(key); if (kind === "belongsTo") { return key + "_id"; } else if (kind === "hasMany") { return Ember.String.singularize(key) + "_ids"; } else { return key; } }, /** Underscores the JSON root keys when serializing. @method serializeIntoHash @param {Object} hash @param {subclass of DS.Model} type @param {DS.Model} record @param {Object} options */ serializeIntoHash: function(data, type, record, options) { var root = Ember.String.decamelize(type.typeKey); data[root] = this.serialize(record, options); }, /** Serializes a polymorphic type as a fully capitalized model name. @method serializePolymorphicType @param {DS.Model} record @param {Object} json @param relationship */ serializePolymorphicType: function(record, json, relationship) { var key = relationship.key, belongsTo = get(record, key); if (belongsTo) { key = this.keyForAttribute(key); json[key + "_type"] = Ember.String.capitalize(belongsTo.constructor.typeKey); } }, // EXTRACT /** Extracts the model typeKey from underscored root objects. @method typeForRoot @param {String} root @return String the model's typeKey */ typeForRoot: function(root) { var camelized = Ember.String.camelize(root); return Ember.String.singularize(camelized); }, /** Add extra step to `DS.RESTSerializer.normalize` so links are normalized. If your payload looks like: ```js { "post": { "id": 1, "title": "Rails is omakase", "links": { "flagged_comments": "api/comments/flagged" } } } ``` The normalized version would look like this ```js { "post": { "id": 1, "title": "Rails is omakase", "links": { "flaggedComments": "api/comments/flagged" } } } ``` @method normalize @param {subclass of DS.Model} type @param {Object} hash @param {String} prop @return Object */ normalize: function(type, hash, prop) { this.normalizeLinks(hash); return this._super(type, hash, prop); }, /** Convert `snake_cased` links to `camelCase` @method normalizeLinks @param {Object} hash */ normalizeLinks: function(data){ if (data.links) { var links = data.links; for (var link in links) { var camelizedLink = Ember.String.camelize(link); if (camelizedLink !== link) { links[camelizedLink] = links[link]; delete links[link]; } } } }, /** Normalize the polymorphic type from the JSON. Normalize: ```js { id: "1" minion: { type: "evil_minion", id: "12"} } ``` To: ```js { id: "1" minion: { type: "evilMinion", id: "12"} } ``` @method normalizeRelationships @private */ normalizeRelationships: function(type, hash) { var payloadKey, payload; if (this.keyForRelationship) { type.eachRelationship(function(key, relationship) { if (relationship.options.polymorphic) { payloadKey = this.keyForAttribute(key); payload = hash[payloadKey]; if (payload && payload.type) { payload.type = this.typeForRoot(payload.type); } else if (payload && relationship.kind === "hasMany") { var self = this; forEach(payload, function(single) { single.type = self.typeForRoot(single.type); }); } } else { payloadKey = this.keyForRelationship(key, relationship.kind); payload = hash[payloadKey]; } hash[key] = payload; if (key !== payloadKey) { delete hash[payloadKey]; } }, this); } } }); }(Ember, DS)); ;