Skip to content

Commit 44b8573

Browse files
committed
Improve the merge of cycling references
1 parent e089d5a commit 44b8573

2 files changed

Lines changed: 242 additions & 2 deletions

File tree

lib/serializer-utils.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@
22
var isPlainObject = require('lodash/isPlainObject');
33
var isFunction = require('lodash/isFunction');
44
var _find = require('lodash/find');
5-
var _extend = require('lodash/extend');
5+
var _merge = require('lodash/merge');
6+
var _defaultsDeep = require('lodash/defaultsDeep');
7+
var _identity = require('lodash/identity');
68
var _transform = require('lodash/transform');
79
var _mapValues = require('lodash/mapValues');
810
var _mapKeys = require('lodash/mapKeys');
911
var _pick = require('lodash/pick');
12+
var _pickBy = require('lodash/pickBy');
1013
var _keys = require('lodash/keys');
1114
var _each = require('lodash/each');
15+
var _isUndefined = require('lodash/isUndefined');
1216
var Inflector = require('./inflector');
1317

1418
module.exports = function (collectionName, record, payload, opts) {
@@ -115,7 +119,13 @@ module.exports = function (collectionName, record, payload, opts) {
115119
function pushToIncluded(dest, include) {
116120
var included = isCompoundDocumentIncluded(dest, include);
117121
if (included) {
118-
included = _extend(included, include);
122+
// Merge relationships
123+
included.relationships = _merge(included.relationships,
124+
_pickBy(include.relationships, _identity));
125+
126+
// Merge attributes
127+
included.attributes = _merge(included.attributes,
128+
_pickBy(include.attributes, _identity));
119129
} else {
120130
if (!dest.included) { dest.included = []; }
121131
dest.included.push(include);

test/serializer.js

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,6 +1255,236 @@ describe('JSON API Serializer', function () {
12551255

12561256
done(null, json);
12571257
});
1258+
1259+
it('should merge the attributes together', function (done) {
1260+
var dataSet = {
1261+
id: '1',
1262+
user: {
1263+
id: '2',
1264+
name: 'Sandro Munda',
1265+
gender: null,
1266+
age: 28,
1267+
address: {
1268+
id: '3',
1269+
zipCode: '49426',
1270+
primaryUser: {
1271+
id: '2',
1272+
name: 'Sandro Munda',
1273+
gender: 'male'
1274+
}
1275+
}
1276+
}
1277+
};
1278+
1279+
var json = new JSONAPISerializer('cycling', {
1280+
attributes: ['user'],
1281+
user: {
1282+
ref: 'id',
1283+
attributes: ['name', 'address', 'gender', 'age'],
1284+
address: {
1285+
ref: 'id',
1286+
attributes: ['zipCode', 'primaryUser'],
1287+
primaryUser: {
1288+
ref: 'id',
1289+
attributes: ['name', 'gender']
1290+
}
1291+
}
1292+
},
1293+
keyForAttribute: 'camelCase',
1294+
typeForAttribute: function (type) {
1295+
if (type === 'primaryUser') { return 'users'; }
1296+
return undefined;
1297+
}
1298+
}).serialize(dataSet);
1299+
1300+
expect(json.included).contains({
1301+
type: 'users',
1302+
id: '2',
1303+
attributes: { name: 'Sandro Munda', gender: 'male', age: 28 },
1304+
relationships: { address: { data: { type: 'addresses', id: '3' } } }
1305+
});
1306+
1307+
expect(json.included).contains({
1308+
type: 'addresses',
1309+
id: '3',
1310+
attributes: { zipCode: '49426' },
1311+
relationships: { primaryUser: { data: { type: 'users', id: '2' } } }
1312+
});
1313+
1314+
done(null, json);
1315+
});
1316+
1317+
it('should merge the attributes together (opposite)', function (done) {
1318+
var dataSet = {
1319+
id: '1',
1320+
user: {
1321+
id: '2',
1322+
name: 'Sandro Munda',
1323+
gender: null,
1324+
address: {
1325+
id: '3',
1326+
zipCode: '49426',
1327+
primaryUser: {
1328+
id: '2',
1329+
name: 'Sandro Munda',
1330+
gender: 'male',
1331+
age: 28
1332+
}
1333+
}
1334+
}
1335+
};
1336+
1337+
var json = new JSONAPISerializer('cycling', {
1338+
attributes: ['user'],
1339+
user: {
1340+
ref: 'id',
1341+
attributes: ['name', 'address', 'gender'],
1342+
address: {
1343+
ref: 'id',
1344+
attributes: ['zipCode', 'primaryUser'],
1345+
primaryUser: {
1346+
ref: 'id',
1347+
attributes: ['name', 'gender', 'age']
1348+
}
1349+
}
1350+
},
1351+
keyForAttribute: 'camelCase',
1352+
typeForAttribute: function (type) {
1353+
if (type === 'primaryUser') { return 'users'; }
1354+
return undefined;
1355+
}
1356+
}).serialize(dataSet);
1357+
1358+
expect(json.included).contains({
1359+
type: 'users',
1360+
id: '2',
1361+
attributes: { name: 'Sandro Munda', gender: 'male', age: 28 },
1362+
relationships: { address: { data: { type: 'addresses', id: '3' } } }
1363+
});
1364+
1365+
expect(json.included).contains({
1366+
type: 'addresses',
1367+
id: '3',
1368+
attributes: { zipCode: '49426' },
1369+
relationships: { primaryUser: { data: { type: 'users', id: '2' } } }
1370+
});
1371+
1372+
done(null, json);
1373+
});
1374+
1375+
it('should ignore the attribute override with a falsy value', function (done) {
1376+
var dataSet = {
1377+
id: '1',
1378+
user: {
1379+
id: '2',
1380+
name: 'Sandro Munda',
1381+
gender: 'male',
1382+
address: {
1383+
id: '3',
1384+
zipCode: '49426',
1385+
primaryUser: {
1386+
id: '2',
1387+
name: 'Sandro Munda',
1388+
gender: null
1389+
}
1390+
}
1391+
}
1392+
};
1393+
1394+
var json = new JSONAPISerializer('cycling', {
1395+
attributes: ['user'],
1396+
user: {
1397+
ref: 'id',
1398+
attributes: ['name', 'address', 'gender'],
1399+
address: {
1400+
ref: 'id',
1401+
attributes: ['zipCode', 'primaryUser'],
1402+
primaryUser: {
1403+
ref: 'id',
1404+
attributes: ['name', 'gender']
1405+
}
1406+
}
1407+
},
1408+
keyForAttribute: 'camelCase',
1409+
typeForAttribute: function (type) {
1410+
if (type === 'primaryUser') { return 'users'; }
1411+
return undefined;
1412+
}
1413+
}).serialize(dataSet);
1414+
1415+
expect(json.included).contains({
1416+
type: 'users',
1417+
id: '2',
1418+
attributes: { name: 'Sandro Munda', gender: 'male' },
1419+
relationships: { address: { data: { type: 'addresses', id: '3' } } }
1420+
});
1421+
1422+
expect(json.included).contains({
1423+
type: 'addresses',
1424+
id: '3',
1425+
attributes: { zipCode: '49426' },
1426+
relationships: { primaryUser: { data: { type: 'users', id: '2' } } }
1427+
});
1428+
1429+
done(null, json);
1430+
});
1431+
1432+
it('should ignore the attribute override with a falsy value (opposite)', function (done) {
1433+
var dataSet = {
1434+
id: '1',
1435+
user: {
1436+
id: '2',
1437+
name: 'Sandro Munda',
1438+
gender: null,
1439+
address: {
1440+
id: '3',
1441+
zipCode: '49426',
1442+
primaryUser: {
1443+
id: '2',
1444+
name: 'Sandro Munda',
1445+
gender: 'male'
1446+
}
1447+
}
1448+
}
1449+
};
1450+
1451+
var json = new JSONAPISerializer('cycling', {
1452+
attributes: ['user'],
1453+
user: {
1454+
ref: 'id',
1455+
attributes: ['name', 'address', 'gender'],
1456+
address: {
1457+
ref: 'id',
1458+
attributes: ['zipCode', 'primaryUser'],
1459+
primaryUser: {
1460+
ref: 'id',
1461+
attributes: ['name', 'gender']
1462+
}
1463+
}
1464+
},
1465+
keyForAttribute: 'camelCase',
1466+
typeForAttribute: function (type) {
1467+
if (type === 'primaryUser') { return 'users'; }
1468+
return undefined;
1469+
}
1470+
}).serialize(dataSet);
1471+
1472+
expect(json.included).contains({
1473+
type: 'users',
1474+
id: '2',
1475+
attributes: { name: 'Sandro Munda', gender: 'male' },
1476+
relationships: { address: { data: { type: 'addresses', id: '3' } } }
1477+
});
1478+
1479+
expect(json.included).contains({
1480+
type: 'addresses',
1481+
id: '3',
1482+
attributes: { zipCode: '49426' },
1483+
relationships: { primaryUser: { data: { type: 'users', id: '2' } } }
1484+
});
1485+
1486+
done(null, json);
1487+
});
12581488
});
12591489

12601490
describe('Top level links with an array of resources', function () {

0 commit comments

Comments
 (0)