Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUGFIX release] Normalize attrs keys #3910

Merged
merged 1 commit into from
Nov 11, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -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];
}
}
Expand Down Expand Up @@ -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]) {
Expand Down Expand Up @@ -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');
Expand Down Expand Up @@ -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");
}
Expand Down Expand Up @@ -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");
}
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