From 45e6db99298f13db732b4b932eef4df5d733a3a5 Mon Sep 17 00:00:00 2001 From: Manuel Wiedenmann Date: Fri, 6 Nov 2015 11:26:32 +0100 Subject: [PATCH] [BUGFIX release] Normalize attrs keys --- .../lib/serializers/json-api-serializer.js | 13 ++--- .../lib/serializers/json-serializer.js | 29 ++++++---- .../serializers/json-api-serializer-test.js | 53 ++++++++++++++++++- .../serializers/json-serializer-test.js | 24 +++++++++ .../serializers/rest-serializer-test.js | 22 ++++++++ 5 files changed, 124 insertions(+), 17 deletions(-) diff --git a/packages/ember-data/lib/serializers/json-api-serializer.js b/packages/ember-data/lib/serializers/json-api-serializer.js index f90bcd0d353..b398ebeefaa 100644 --- a/packages/ember-data/lib/serializers/json-api-serializer.js +++ b/packages/ember-data/lib/serializers/json-api-serializer.js @@ -376,18 +376,19 @@ const JSONAPISerializer = JSONSerializer.extend({ @param {Object} attribute */ serializeAttribute: function(snapshot, json, key, attribute) { - var type = attribute.type; + const type = attribute.type; if (this._canSerialize(key)) { json.attributes = json.attributes || {}; - var value = snapshot.attr(key); + let value = snapshot.attr(key); if (type) { - var transform = this.transformFor(type); + const transform = this.transformFor(type); value = transform.serialize(value); } - var payloadKey = this._getMappedKey(key); + let payloadKey = this._getMappedKey(key, snapshot.type); + if (payloadKey === key) { payloadKey = this.keyForAttribute(key, 'serialize'); } @@ -411,7 +412,7 @@ const JSONAPISerializer = JSONSerializer.extend({ json.relationships = json.relationships || {}; - var payloadKey = this._getMappedKey(key); + var payloadKey = this._getMappedKey(key, snapshot.type); if (payloadKey === key) { payloadKey = this.keyForRelationship(key, 'belongsTo', 'serialize'); } @@ -444,7 +445,7 @@ const JSONAPISerializer = JSONSerializer.extend({ json.relationships = json.relationships || {}; - var payloadKey = this._getMappedKey(key); + var payloadKey = this._getMappedKey(key, snapshot.type); if (payloadKey === key && this.keyForRelationship) { payloadKey = this.keyForRelationship(key, 'hasMany', 'serialize'); } diff --git a/packages/ember-data/lib/serializers/json-serializer.js b/packages/ember-data/lib/serializers/json-serializer.js index d3480799b58..f4f86cd5f9f 100644 --- a/packages/ember-data/lib/serializers/json-serializer.js +++ b/packages/ember-data/lib/serializers/json-serializer.js @@ -710,17 +710,26 @@ export default Serializer.extend({ @method normalizeUsingDeclaredMapping @private */ - normalizeUsingDeclaredMapping: function(typeClass, hash) { + normalizeUsingDeclaredMapping: function(modelClass, hash) { var attrs = get(this, 'attrs'); - var payloadKey, key; + var payloadKey, normalizedKey, key; if (attrs) { for (key in attrs) { - payloadKey = this._getMappedKey(key); + payloadKey = this._getMappedKey(key, modelClass); + if (!hash.hasOwnProperty(payloadKey)) { continue; } - if (payloadKey !== key) { - hash[key] = hash[payloadKey]; + if (get(modelClass, 'attributes').has(key)) { + normalizedKey = this.keyForAttribute(key); + } + + if (get(modelClass, 'relationshipsByName').has(key)) { + normalizedKey = this.keyForRelationship(key); + } + + if (payloadKey !== normalizedKey) { + hash[normalizedKey] = hash[payloadKey]; delete hash[payloadKey]; } } @@ -749,7 +758,9 @@ export default Serializer.extend({ @param {String} key @return {String} key */ - _getMappedKey: function(key) { + _getMappedKey: function(key, modelClass) { + Ember.assert('There is no attribute or relationship with the name `' + key + '` on `' + modelClass.modelName + '`. Check your serializers attrs hash.', get(modelClass, 'attributes').has(key) || get(modelClass, 'relationshipsByName').has(key)); + var attrs = get(this, 'attrs'); var mappedKey; if (attrs && attrs[key]) { @@ -1062,7 +1073,7 @@ export default Serializer.extend({ // if provided, use the mapping provided by `attrs` in // the serializer - var payloadKey = this._getMappedKey(key); + var payloadKey = this._getMappedKey(key, snapshot.type); if (payloadKey === key && this.keyForAttribute) { payloadKey = this.keyForAttribute(key, 'serialize'); @@ -1107,7 +1118,7 @@ export default Serializer.extend({ // if provided, use the mapping provided by `attrs` in // the serializer - var payloadKey = this._getMappedKey(key); + var payloadKey = this._getMappedKey(key, snapshot.type); if (payloadKey === key && this.keyForRelationship) { payloadKey = this.keyForRelationship(key, "belongsTo", "serialize"); } @@ -1159,7 +1170,7 @@ export default Serializer.extend({ if (hasMany !== undefined) { // if provided, use the mapping provided by `attrs` in // the serializer - var payloadKey = this._getMappedKey(key); + var payloadKey = this._getMappedKey(key, snapshot.type); if (payloadKey === key && this.keyForRelationship) { payloadKey = this.keyForRelationship(key, "hasMany", "serialize"); } diff --git a/packages/ember-data/tests/integration/serializers/json-api-serializer-test.js b/packages/ember-data/tests/integration/serializers/json-api-serializer-test.js index 29df8d57943..a64fd5b15d0 100644 --- a/packages/ember-data/tests/integration/serializers/json-api-serializer-test.js +++ b/packages/ember-data/tests/integration/serializers/json-api-serializer-test.js @@ -3,7 +3,7 @@ var env, store, serializer; var get = Ember.get; var run = Ember.run; -var User, Handle, GithubHandle, TwitterHandle, Company; +var User, Handle, GithubHandle, TwitterHandle, Company, Project; module('integration/serializers/json-api-serializer - JSONAPISerializer', { setup: function() { @@ -32,6 +32,10 @@ module('integration/serializers/json-api-serializer - JSONAPISerializer', { employees: DS.hasMany('user', { async: true }) }); + Project = DS.Model.extend({ + 'company-name': DS.attr('string') + }); + env = setupStore({ adapter: DS.JSONAPIAdapter, @@ -39,7 +43,8 @@ module('integration/serializers/json-api-serializer - JSONAPISerializer', { handle: Handle, 'github-handle': GithubHandle, 'twitter-handle': TwitterHandle, - company: Company + company: Company, + project: Project }); store = env.store; @@ -125,6 +130,7 @@ test('Warns when normalizing an unknown type', function() { test('Serializer should respect the attrs hash when extracting attributes and relationships', function() { env.registry.register("serializer:user", DS.JSONAPISerializer.extend({ attrs: { + firstName: 'firstname_attribute_key', title: "title_attribute_key", company: { key: 'company_relationship_key' } } @@ -135,6 +141,7 @@ test('Serializer should respect the attrs hash when extracting attributes and re type: 'users', id: '1', attributes: { + 'firstname_attribute_key': 'Yehuda', 'title_attribute_key': 'director' }, relationships: { @@ -154,6 +161,7 @@ test('Serializer should respect the attrs hash when extracting attributes and re var user = env.store.serializerFor("user").normalizeResponse(env.store, User, jsonHash, '1', 'findRecord'); + equal(user.data.attributes.firstName, 'Yehuda'); equal(user.data.attributes.title, "director"); deepEqual(user.data.relationships.company.data, { id: "2", type: "company" }); }); @@ -161,6 +169,7 @@ test('Serializer should respect the attrs hash when extracting attributes and re test('Serializer should respect the attrs hash when serializing attributes and relationships', function() { env.registry.register("serializer:user", DS.JSONAPISerializer.extend({ attrs: { + firstName: 'firstname_attribute_key', title: "title_attribute_key", company: { key: 'company_relationship_key' } } @@ -184,5 +193,45 @@ test('Serializer should respect the attrs hash when serializing attributes and r var payload = env.store.serializerFor("user").serialize(user._createSnapshot()); equal(payload.data.relationships['company_relationship_key'].data.id, "1"); + equal(payload.data.attributes['firstname_attribute_key'], 'Yehuda'); equal(payload.data.attributes['title_attribute_key'], "director"); }); + +test('Serializer should respect the attrs hash when extracting attributes with not camelized keys', function() { + env.registry.register('serializer:project', DS.JSONAPISerializer.extend({ + attrs: { + 'company-name': 'company_name' + } + })); + + var jsonHash = { + data: { + type: 'projects', + id: '1', + attributes: { + 'company_name': 'Tilde Inc.' + } + } + }; + + var project = env.store.serializerFor('project').normalizeResponse(env.store, User, jsonHash, '1', 'findRecord'); + + equal(project.data.attributes['company-name'], 'Tilde Inc.'); +}); + +test('Serializer should respect the attrs hash when serializing attributes with not camelized keys', function() { + env.registry.register('serializer:project', DS.JSONAPISerializer.extend({ + attrs: { + 'company-name': 'company_name' + } + })); + var project; + + run(function() { + project = env.store.createRecord('project', { 'company-name': 'Tilde Inc.' }); + }); + + var payload = env.store.serializerFor('project').serialize(project._createSnapshot()); + + equal(payload.data.attributes['company_name'], 'Tilde Inc.'); +}); diff --git a/packages/ember-data/tests/integration/serializers/json-serializer-test.js b/packages/ember-data/tests/integration/serializers/json-serializer-test.js index 79fd398d4ab..7256902661c 100644 --- a/packages/ember-data/tests/integration/serializers/json-serializer-test.js +++ b/packages/ember-data/tests/integration/serializers/json-serializer-test.js @@ -289,6 +289,30 @@ test('Serializer should respect the attrs hash when extracting records', functio deepEqual(post.data.relationships.comments.data, [{ id: "1", type: "comment" }, { id: "2", type: "comment" }]); }); +test('Serializer should map `attrs` attributes directly when keyForAttribute also has a transform', function() { + Post = DS.Model.extend({ + authorName: DS.attr('string') + }); + env = setupStore({ + post: Post + }); + env.registry.register("serializer:post", DS.JSONSerializer.extend({ + keyForAttribute: Ember.String.underscore, + attrs: { + authorName: 'author_name_key' + } + })); + + var jsonHash = { + id: "1", + author_name_key: "DHH" + }; + + var post = env.store.serializerFor("post").normalizeResponse(env.store, Post, jsonHash, '1', 'findRecord'); + + equal(post.data.attributes.authorName, "DHH"); +}); + test('Serializer should respect the attrs hash when serializing records', function() { Post.reopen({ parentPost: DS.belongsTo('post', { inverse: null, async: true }) diff --git a/packages/ember-data/tests/integration/serializers/rest-serializer-test.js b/packages/ember-data/tests/integration/serializers/rest-serializer-test.js index 95ae9a9ca14..a302ac5062a 100644 --- a/packages/ember-data/tests/integration/serializers/rest-serializer-test.js +++ b/packages/ember-data/tests/integration/serializers/rest-serializer-test.js @@ -409,6 +409,28 @@ test('normalize should allow for different levels of normalization', function() equal(array.data[0].relationships.superVillain.data.id, 1); }); +test('normalize should allow for different levels of normalization - attributes', function() { + env.registry.register('serializer:application', DS.RESTSerializer.extend({ + attrs: { + name: 'full_name' + }, + keyForAttribute: function(attr) { + return Ember.String.decamelize(attr); + } + })); + + var jsonHash = { + evilMinions: [{ id: "1", full_name: "Tom Dale" }] + }; + var array; + + run(function() { + array = env.restSerializer.normalizeResponse(env.store, EvilMinion, jsonHash, null, 'findAll'); + }); + + equal(array.data[0].attributes.name, 'Tom Dale'); +}); + test("serializeIntoHash", function() { run(function() { league = env.store.createRecord('home-planet', { name: "Umber", id: "123" });