Skip to content

Commit

Permalink
Merge pull request #3910 from fsmanuel/fix/attrs-key
Browse files Browse the repository at this point in the history
[BUGFIX release] Normalize attrs keys
  • Loading branch information
bmac committed Nov 11, 2015
2 parents d4a5bf1 + 45e6db9 commit aa18100
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 17 deletions.
13 changes: 7 additions & 6 deletions packages/ember-data/lib/serializers/json-api-serializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
}
Expand All @@ -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');
}
Expand Down Expand Up @@ -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');
}
Expand Down
29 changes: 20 additions & 9 deletions packages/ember-data/lib/serializers/json-serializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -714,17 +714,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];
}
}
Expand Down Expand Up @@ -753,7 +762,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]) {
Expand Down Expand Up @@ -1066,7 +1077,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');
Expand Down Expand Up @@ -1111,7 +1122,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");
}
Expand Down Expand Up @@ -1163,7 +1174,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");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -32,14 +32,19 @@ 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,

user: User,
handle: Handle,
'github-handle': GithubHandle,
'twitter-handle': TwitterHandle,
company: Company
company: Company,
project: Project
});

store = env.store;
Expand Down Expand Up @@ -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' }
}
Expand All @@ -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: {
Expand All @@ -154,13 +161,15 @@ 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" });
});

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' }
}
Expand All @@ -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.');
});
Original file line number Diff line number Diff line change
Expand Up @@ -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 })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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" });
Expand Down

0 comments on commit aa18100

Please sign in to comment.