Skip to content

Commit 2cf9005

Browse files
committed
Add linkage from relationships.data to included
1 parent c313beb commit 2cf9005

File tree

5 files changed

+76
-73
lines changed

5 files changed

+76
-73
lines changed

lib/serializer.js

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -276,22 +276,36 @@ function handleIncludes (resp, includes, relations) {
276276
if (!relation) {
277277
throw RelUtils.getInvalidIncludesError('Can\'t locate relationship "' + include + '" to include');
278278
}
279+
280+
resource.relationships[include] = resource.relationships[include] || {};
281+
279282
if (resource.relationships[include] && resource.attributes[include]) {
280283
if (_.isArray(resource.attributes[include])) {
281284
embeds = resource.attributes[include].map(function (rel) {
282285
rel = utils.clone(rel);
283-
return createCompoundIncludes(rel, propertyKey, plural);
286+
return createCompoundIncludes(rel, propertyKey, relation.keyTo, plural);
284287
});
285288
embeds = _.compact(embeds);
286289

287-
resource.attributes[include] = _.map(embeds, 'id');
290+
resource.relationships[include].data = resource.attributes[include].map(function (relData) {
291+
return {
292+
id: String(relData[propertyKey]),
293+
type: plural
294+
};
295+
});
288296
} else {
289297
var rel = utils.clone(resource.attributes[include]);
290-
var compoundIncludes = createCompoundIncludes(rel, propertyKey, plural);
291-
resource.attributes[include] = String(resource.attributes[include][propertyKey]);
298+
var compoundIncludes = createCompoundIncludes(rel, propertyKey, relation.keyFrom, plural);
292299

300+
resource.relationships[include].data = {
301+
id: String(resource.attributes[include][propertyKey]),
302+
type: plural
303+
};
293304
embeds.push(compoundIncludes);
294305
}
306+
delete resource.attributes[relation.keyFrom];
307+
delete resource.attributes[relation.keyTo];
308+
delete resource.attributes[include];
295309
}
296310
return embeds;
297311
});
@@ -307,15 +321,16 @@ function handleIncludes (resp, includes, relations) {
307321
* @private
308322
* @memberOf {Serializer}
309323
* @param {Object} relationship
310-
* @param {String} id
324+
* @param {String} key
311325
* @param {String} type
312326
* @return {Object}
313327
*/
314-
function createCompoundIncludes (relationship, key, type) {
328+
function createCompoundIncludes (relationship, key, fk, type) {
315329
var compoundInclude = makeRelation(type, String(relationship[key]));
316330

317331
// remove the id key since its part of the base compound document, not part of attributes
318332
delete relationship[key];
333+
delete relationship[fk];
319334

320335
// The rest of the data goes in the attributes
321336
compoundInclude.attributes = relationship;

test/belongsTo.test.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,8 @@ describe('loopback json api belongsTo relationships', function () {
215215
});
216216
});
217217

218-
it.skip('should return included data as a compound document using key "included"', function (done) {
219-
request(app).get('/comments?filter={"include":"post"}')
218+
it('should return included data as a compound document using key "included"', function (done) {
219+
request(app).get('/comments?filter[include]=post')
220220
.end(function (err, res) {
221221
expect(err).to.equal(null);
222222
expect(res.body.data[0].relationships).to.be.an('object');
@@ -229,8 +229,8 @@ describe('loopback json api belongsTo relationships', function () {
229229
expect(res.body.data[0].relationships.post.links.related).to.match(/comments\/1\/post/);
230230
expect(res.body.included).to.be.an('array');
231231
expect(res.body.included.length).to.equal(1);
232-
expect(res.body.included[0]).to.have.all.keys('type', 'id', 'attributes', 'links');
233-
expect(res.body.included[0].type).to.equal('post');
232+
expect(res.body.included[0]).to.have.all.keys('type', 'id', 'attributes');
233+
expect(res.body.included[0].type).to.equal('posts');
234234
expect(res.body.included[0].id).to.equal('1');
235235
done();
236236
});

test/hasMany.test.js

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -171,21 +171,24 @@ describe('loopback json api hasMany relationships', function () {
171171
});
172172
});
173173

174-
it.skip('should return included data as a compound document using key "included"', function (done) {
175-
request(app).get('/posts?filter={"include":"comments"}')
174+
it('should return included data as a compound document using key "included"', function (done) {
175+
request(app).get('/posts?filter[include]=comments')
176176
.end(function (err, res) {
177177
expect(err).to.equal(null);
178178
expect(res.body.data[0].relationships).to.be.an('object');
179179
expect(res.body.data[0].relationships.comments).to.be.an('object');
180-
expect(res.body.data[0].relationships.comments.data).to.deep.equal({
180+
expect(res.body.data[0].relationships.comments.data).to.deep.equal([{
181181
type: 'comments',
182182
id: '1'
183-
});
183+
}, {
184+
type: 'comments',
185+
id: '2'
186+
}]);
184187
expect(res.body.data[0].relationships.comments.links).to.be.an('object');
185188
expect(res.body.data[0].relationships.comments.links.related).to.match(/posts\/1\/comments/);
186189
expect(res.body.included).to.be.an('array');
187-
expect(res.body.included.length).to.equal(1);
188-
expect(res.body.included[0]).to.have.all.keys('type', 'id', 'attributes', 'links');
190+
expect(res.body.included.length).to.equal(2);
191+
expect(res.body.included[0]).to.have.all.keys('type', 'id', 'attributes');
189192
expect(res.body.included[0].type).to.equal('comments');
190193
expect(res.body.included[0].id).to.equal('1');
191194
done();
@@ -204,12 +207,11 @@ describe('loopback json api hasMany relationships', function () {
204207
expect(err).to.equal(null);
205208
expect(res.body.included).to.be.an('array');
206209
expect(res.body.included.length).to.equal(2);
207-
expect(res.body.data[0].attributes.comments).to.deep.equal(['1', '2']);
210+
expect(res.body.data[0].attributes).to.not.have.keys('comments');
208211
expect(res.body.included[0]).to.deep.equal({
209212
id: '1',
210213
type: 'comments',
211214
attributes: {
212-
postId: 1,
213215
title: 'My comment',
214216
comment: 'My comment text'
215217
}
@@ -218,7 +220,6 @@ describe('loopback json api hasMany relationships', function () {
218220
id: '2',
219221
type: 'comments',
220222
attributes: {
221-
postId: 1,
222223
title: 'My second comment',
223224
comment: 'My second comment text'
224225
}
@@ -256,21 +257,24 @@ describe('loopback json api hasMany relationships', function () {
256257
});
257258
});
258259

259-
it.skip('should return included data as a compound document using key "included"', function (done) {
260-
request(app).get('/posts/1?filter={"include":"comments"}')
260+
it('should return included data as a compound document using key "included"', function (done) {
261+
request(app).get('/posts/1?filter[include]=comments')
261262
.end(function (err, res) {
262263
expect(err).to.equal(null);
263264
expect(res.body.data.relationships).to.be.an('object');
264265
expect(res.body.data.relationships.comments).to.be.an('object');
265-
expect(res.body.data.relationships.comments.data).to.deep.equal({
266+
expect(res.body.data.relationships.comments.data).to.deep.equal([{
266267
type: 'comments',
267268
id: '1'
268-
});
269+
}, {
270+
type: 'comments',
271+
id: '2'
272+
}]);
269273
expect(res.body.data.relationships.comments.links).to.be.an('object');
270274
expect(res.body.data.relationships.comments.links.related).to.match(/posts\/1\/comments/);
271275
expect(res.body.included).to.be.an('array');
272-
expect(res.body.included.length).to.equal(1);
273-
expect(res.body.included[0]).to.have.all.keys('type', 'id', 'attributes', 'links');
276+
expect(res.body.included.length).to.equal(2);
277+
expect(res.body.included[0]).to.have.all.keys('type', 'id', 'attributes');
274278
expect(res.body.included[0].type).to.equal('comments');
275279
expect(res.body.included[0].id).to.equal('1');
276280
done();

test/hasManyRelationships.test.js

Lines changed: 26 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -11,91 +11,77 @@ describe('loopback json api hasMany relationships', function () {
1111
ds = loopback.createDataSource('memory');
1212

1313
Post = ds.createModel('post', {
14-
id: {
15-
type: Number,
16-
id: true
17-
},
1814
title: String,
1915
content: String
2016
});
2117
app.model(Post);
2218

2319
Comment = ds.createModel('comment', {
24-
id: {
25-
type: Number,
26-
id: true
27-
},
28-
postId: Number,
2920
title: String,
3021
comment: String
3122
});
3223
Comment.settings.plural = 'comments';
3324
app.model(Comment);
3425

3526
Author = ds.createModel('author', {
36-
id: {
37-
type: Number,
38-
id: true
39-
},
4027
firstName: String,
4128
lastName: String
4229
});
4330
Author.settings.plural = 'authors';
4431
app.model(Author);
4532

46-
Post.hasMany(Comment, {
47-
as: 'comments',
48-
foreignKey: 'postId'
49-
});
50-
Post.hasOne(Author, {
51-
as: 'author',
52-
foreignKey: 'id'
53-
});
33+
Post.hasMany(Comment);
34+
Comment.belongsTo(Post);
35+
Post.belongsTo(Author);
36+
Author.hasMany(Post);
5437

5538
app.use(loopback.rest());
5639
JSONAPIComponent(app, {restApiRoot: '/'});
5740
});
5841

59-
describe('Requesting multiple via `includes` should return relationships', function (done) {
42+
describe('Multiple `includes`', function (done) {
6043
beforeEach(function (done) {
6144
Author.create({
6245
firstName: 'Joe',
6346
lastName: 'Shmoe'
6447
}, function (err, author) {
6548
expect(err).to.equal(null);
66-
Post.create({
49+
author.posts.create({
6750
title: 'my post',
6851
content: 'my post content'
6952
}, function (err, post) {
7053
expect(err).to.equal(null);
71-
post.comments.create({
54+
post.comments.create([{
7255
title: 'My comment',
7356
comment: 'My comment text'
74-
}, function () {
75-
post.comments.create({
76-
title: 'My second comment',
77-
comment: 'My second comment text'
78-
}, done);
79-
});
57+
}, {
58+
title: 'My second comment',
59+
comment: 'My second comment text'
60+
}], done);
8061
});
8162
});
8263
});
8364

84-
it('should return stuff', function (done) {
65+
it('should sideload author and comments', function (done) {
8566
request(app).get('/posts/1/?include=author,comments')
8667
.expect(200)
8768
.end(function (err, res) {
69+
var data = res.body.data;
8870
expect(err).to.equal(null);
89-
//expect(res.body.data.id).to.equal('1');
90-
expect(res.body.data.type).to.equal('posts');
91-
expect(res.body.data.relationships).to.be.a('object');
92-
expect(res.body.data.relationships.author).to.be.a('object');
93-
expect(res.body.data.relationships.comments).to.be.a('object');
94-
expect(res.body.data.attributes).to.deep.equal({
71+
expect(data.id).to.equal('1');
72+
expect(data.type).to.equal('posts');
73+
expect(data.relationships).to.be.a('object');
74+
expect(data.relationships.author).to.be.a('object');
75+
expect(data.relationships.author.data.id).to.equal('1');
76+
expect(data.relationships.author.data.type).to.equal('authors');
77+
expect(data.relationships.comments.data).to.be.a('array');
78+
expect(data.relationships.comments.data[0].id).to.equal('1');
79+
expect(data.relationships.comments.data[0].type).to.equal('comments');
80+
expect(data.relationships.comments.data[1].id).to.equal('2');
81+
expect(data.relationships.comments.data[1].type).to.equal('comments');
82+
expect(data.attributes).to.deep.equal({
9583
title: 'my post',
96-
content: 'my post content',
97-
author: '1',
98-
comments: [ '1', '2' ]
84+
content: 'my post content'
9985
});
10086
expect(res.body.included).to.be.an('array');
10187
expect(res.body.included.length).to.equal(3);
@@ -111,7 +97,6 @@ describe('loopback json api hasMany relationships', function () {
11197
id: '1',
11298
type: 'comments',
11399
attributes: {
114-
postId: 1,
115100
title: 'My comment',
116101
comment: 'My comment text'
117102
}
@@ -120,7 +105,6 @@ describe('loopback json api hasMany relationships', function () {
120105
id: '2',
121106
type: 'comments',
122107
attributes: {
123-
postId: 1,
124108
title: 'My second comment',
125109
comment: 'My second comment text'
126110
}

test/hasOne.test.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,8 @@ describe('loopback json api hasOne relationships', function () {
166166
});
167167
});
168168

169-
it.skip('should return included data as a compound document using key "included"', function (done) {
170-
request(app).get('/posts?filter={"include":"author"}')
169+
it('should return included data as a compound document using key "included"', function (done) {
170+
request(app).get('/posts?filter[include]=author')
171171
.end(function (err, res) {
172172
expect(err).to.equal(null);
173173
expect(res.body.data[0].relationships).to.be.an('object');
@@ -180,7 +180,7 @@ describe('loopback json api hasOne relationships', function () {
180180
expect(res.body.data[0].relationships.author.links.related).to.match(/posts\/1\/author/);
181181
expect(res.body.included).to.be.an('array');
182182
expect(res.body.included.length).to.equal(1);
183-
expect(res.body.included[0]).to.have.all.keys('type', 'id', 'attributes', 'links');
183+
expect(res.body.included[0]).to.have.all.keys('type', 'id', 'attributes');
184184
expect(res.body.included[0].type).to.equal('people');
185185
expect(res.body.included[0].id).to.equal('1');
186186
done();
@@ -240,8 +240,8 @@ describe('loopback json api hasOne relationships', function () {
240240
});
241241
});
242242

243-
it.skip('should return included data as a compound document using key "included"', function (done) {
244-
request(app).get('/posts/1?filter={"include":"author"}')
243+
it('should return included data as a compound document using key "included"', function (done) {
244+
request(app).get('/posts/1?filter[include]=author')
245245
.end(function (err, res) {
246246
expect(err).to.equal(null);
247247
expect(res.body.data.relationships).to.be.an('object');
@@ -254,7 +254,7 @@ describe('loopback json api hasOne relationships', function () {
254254
expect(res.body.data.relationships.author.links.related).to.match(/posts\/1\/author/);
255255
expect(res.body.included).to.be.an('array');
256256
expect(res.body.included.length).to.equal(1);
257-
expect(res.body.included[0]).to.have.all.keys('type', 'id', 'attributes', 'links');
257+
expect(res.body.included[0]).to.have.all.keys('type', 'id', 'attributes');
258258
expect(res.body.included[0].type).to.equal('people');
259259
expect(res.body.included[0].id).to.equal('1');
260260
done();

0 commit comments

Comments
 (0)