Skip to content

Commit dd9b5a0

Browse files
committed
fix hasMany polymorphic relationship
1 parent 95656ad commit dd9b5a0

File tree

4 files changed

+106
-6
lines changed

4 files changed

+106
-6
lines changed

lib/serialize.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ module.exports = function (app, defaults) {
7171

7272
var relation = model.relations[relationName];
7373
if (relationName && relation) {
74-
if (relation.polymorphic) {
74+
if (relation.polymorphic && utils.relationFkOnModelFrom(relation)) {
7575
var discriminator = utils.clone(ctx.instance)[relation.polymorphic.discriminator];
7676
relatedModel = app.models[discriminator];
7777
} else {

lib/serializer.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ function parseRelations (data, relations, options) {
170170
var fkName = relation.keyTo;
171171

172172
// If relation is belongsTo then fk is the other way around
173-
if (relation.type === 'belongsTo' || relation.type === 'referencesMany') {
173+
if (utils.relationFkOnModelFrom(relation)) {
174174
fkName = relation.keyFrom;
175175
}
176176

@@ -195,7 +195,7 @@ function parseRelations (data, relations, options) {
195195

196196
var fromType = utils.pluralForModel(relation.modelFrom);
197197
var toType = '';
198-
if (relation.polymorphic) {
198+
if (relation.polymorphic && utils.relationFkOnModelFrom(relation)) {
199199
var discriminator = relation.polymorphic.discriminator;
200200
var model = options.app.models[data[discriminator]];
201201
toType = utils.pluralForModel(model);
@@ -328,7 +328,7 @@ function handleIncludes (resp, includes, relations, app) {
328328
var relation = relations[include];
329329
var propertyKey = relation.keyFrom;
330330
var plural = '';
331-
if (relation.polymorphic) {
331+
if (relation.polymorphic && utils.relationFkOnModelFrom(relation)) {
332332
var discriminator = resource.attributes[relation.polymorphic.discriminator];
333333
plural = utils.pluralForModel(app.models[discriminator]);
334334
} else {
@@ -337,7 +337,7 @@ function handleIncludes (resp, includes, relations, app) {
337337
var embeds = [];
338338

339339
// If relation is belongsTo then pk and fk are the other way around
340-
if (relation.type === 'belongsTo' || relation.type === 'referencesMany') {
340+
if (utils.relationFkOnModelFrom(relation)) {
341341
propertyKey = relation.keyTo;
342342
}
343343

lib/utils.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ module.exports = {
1616
urlFromContext: urlFromContext,
1717
primaryKeyForModel: primaryKeyForModel,
1818
shouldNotApplyJsonApi: shouldNotApplyJsonApi,
19-
shouldApplyJsonApi: shouldApplyJsonApi
19+
shouldApplyJsonApi: shouldApplyJsonApi,
20+
relationFkOnModelFrom: relationFkOnModelFrom
2021
};
2122

2223
function primaryKeyForModel (model) {
@@ -204,3 +205,7 @@ function shouldNotApplyJsonApi (ctx, options) {
204205
}
205206
return false;
206207
}
208+
209+
function relationFkOnModelFrom (relation) {
210+
return relation.type === 'belongsTo' || relation.type === 'referencesMany';
211+
}

test/hasManyPolymorphic.test.js

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
var request = require('supertest');
2+
var loopback = require('loopback');
3+
var expect = require('chai').expect;
4+
var JSONAPIComponent = require('../');
5+
var app;
6+
var ds;
7+
var Post;
8+
var File;
9+
10+
describe('loopback json api hasMany polymorphic relationships', function () {
11+
beforeEach(function () {
12+
app = loopback();
13+
app.set('legacyExplorer', false);
14+
ds = loopback.createDataSource('memory');
15+
16+
File = ds.createModel('file', {
17+
id: {type: Number, id: true},
18+
fileName: String,
19+
parentId: Number,
20+
parentType: String
21+
});
22+
File.settings.plural = 'files';
23+
app.model(File);
24+
25+
Post = ds.createModel('post', {
26+
id: {type: Number, id: true},
27+
title: String,
28+
content: String
29+
});
30+
Post.settings.plural = 'posts';
31+
Post.hasMany(File, {
32+
as: 'files',
33+
polymorphic: 'parent'
34+
});
35+
app.model(Post);
36+
37+
app.use(loopback.rest());
38+
JSONAPIComponent(app);
39+
});
40+
41+
describe('Post hasMany Files', function () {
42+
beforeEach(function (done) {
43+
Post.create({
44+
title: 'Post One',
45+
content: 'Content'
46+
}, function (err, post) {
47+
expect(err).to.equal(null);
48+
File.create({
49+
fileName: 'blah.jpg',
50+
parentId: post.id,
51+
parentType: 'post'
52+
}, done);
53+
});
54+
});
55+
56+
it('should have a relationship to Files', function (done) {
57+
request(app).get('/posts/1')
58+
.end(function (err, res) {
59+
expect(err).to.equal(null);
60+
expect(res.body.errors).to.equal(undefined);
61+
expect(res.body.data.relationships.files).to.be.an('object');
62+
done();
63+
});
64+
});
65+
66+
it('should return the Files that belong to this Post when included flag is present', function (done) {
67+
request(app).get('/posts/1?include=files')
68+
.end(function (err, res) {
69+
expect(err).to.equal(null);
70+
expect(res.body.errors).to.equal(undefined);
71+
expect(res.body.included).to.be.an('array');
72+
expect(res.body.included[0].type).to.equal('files');
73+
expect(res.body.included[0].id).to.equal('1');
74+
done();
75+
});
76+
});
77+
78+
it('should return the Files that belong to this Post when following the relationship link', function (done) {
79+
request(app).get('/posts/1')
80+
.end(function (err, res) {
81+
expect(err).to.equal(null);
82+
expect(res.body.errors).to.equal(undefined);
83+
request(app).get(res.body.data.relationships.files.links.related.split('api')[1])
84+
.end(function (err, res) {
85+
expect(err).to.equal(null);
86+
expect(res.body.errors).to.equal(undefined);
87+
expect(res.body.data).to.be.an('array');
88+
expect(res.body.data[0].type).to.equal('files');
89+
expect(res.body.data[0].id).to.equal('1');
90+
done();
91+
});
92+
});
93+
});
94+
});
95+
});

0 commit comments

Comments
 (0)