Skip to content

Commit be3ab33

Browse files
committed
fix(deserializer): unable to create polymorphic relationship #298
1 parent a7083aa commit be3ab33

File tree

4 files changed

+174
-2
lines changed

4 files changed

+174
-2
lines changed

lib/deserializer.js

+15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict'
22

33
var _ = require('lodash')
4+
var utils = require('./utils')
45

56
function defaultBeforeDeserialize (options, cb) {
67
cb(null, options)
@@ -78,6 +79,20 @@ function belongsToRelationships (options) {
7879
if (!relationship.data) {
7980
options.result[fkName] = null
8081
} else {
82+
if (serverRelation.polymorphic) {
83+
// Find the model which has a plural matching 'data.type'
84+
// Allow case insensitive match
85+
var relatedType = relationship.data.type.toLowerCase()
86+
var modelName = _.findKey(model.app.models, function (model) {
87+
var plural = utils.pluralForModel(model)
88+
return plural.toLowerCase() === relatedType
89+
})
90+
if (!modelName) {
91+
return false
92+
}
93+
var discriminator = serverRelation.polymorphic.discriminator
94+
options.result[discriminator] = modelName
95+
}
8196
options.result[fkName] = relationship.data.id
8297
}
8398
})

lib/serializer.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,12 @@ function parseRelations (data, relations, options) {
233233
var toType = ''
234234
if (relation.polymorphic && utils.relationFkOnModelFrom(relation)) {
235235
var discriminator = relation.polymorphic.discriminator
236-
var model = options.app.models[data[discriminator]]
237-
toType = utils.pluralForModel(model)
236+
if (data[discriminator]) {
237+
var model = options.app.models[data[discriminator]]
238+
if (model) {
239+
toType = utils.pluralForModel(model)
240+
}
241+
}
238242
} else {
239243
toType = utils.pluralForModel(relation.modelTo)
240244
}

test/belongsToPolymorphic.test.js

+97
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,101 @@ describe('loopback json api belongsTo polymorphic relationships', function () {
106106
}
107107
)
108108
})
109+
110+
describe('File with no relationship to a Post', function () {
111+
beforeEach(function (done) {
112+
FileModel.create(
113+
{
114+
fileName: 'blah.jpg'
115+
},
116+
done
117+
)
118+
})
119+
120+
it('should return a null value for relationship data', function (done) {
121+
request(app).get('/fileModels/1').end(function (err, res) {
122+
expect(err).to.equal(null)
123+
expect(res.body).to.not.have.key('errors')
124+
expect(res.body.data.relationships.parent).to.be.an('object')
125+
expect(res.body.data.relationships.parent.data).to.equal(null)
126+
done()
127+
})
128+
})
129+
})
130+
131+
describe('Create relationship via API', function () {
132+
beforeEach(function (done) {
133+
Post.create(
134+
{
135+
title: 'Post One',
136+
content: 'Content'
137+
},
138+
done
139+
)
140+
})
141+
142+
it('should define a relationship to Post when file is created', function (
143+
done
144+
) {
145+
request(app)
146+
.post('/fileModels')
147+
.send({
148+
data: {
149+
type: 'fileModels',
150+
attributes: {
151+
fileName: 'blah.jpg'
152+
},
153+
relationships: {
154+
parent: {
155+
data: {
156+
id: 1,
157+
type: 'posts'
158+
}
159+
}
160+
}
161+
}
162+
})
163+
.set('accept', 'application/vnd.api+json')
164+
.set('content-type', 'application/json')
165+
.expect(201)
166+
.end(function (err, res) {
167+
expect(err).to.equal(null)
168+
expect(res.body).to.not.have.key('errors')
169+
expect(res.body.data.relationships.parent).to.be.an('object')
170+
expect(res.body.data.relationships.parent.data).to.be.an('object')
171+
done()
172+
})
173+
})
174+
175+
it('should ignore relationships with an invalid type', function (done) {
176+
request(app)
177+
.post('/fileModels')
178+
.send({
179+
data: {
180+
type: 'fileModels',
181+
attributes: {
182+
fileName: 'blah.jpg'
183+
},
184+
relationships: {
185+
parent: {
186+
data: {
187+
id: 1,
188+
type: 'invalidType'
189+
}
190+
}
191+
}
192+
}
193+
})
194+
.set('accept', 'application/vnd.api+json')
195+
.set('content-type', 'application/json')
196+
.expect(201)
197+
.end(function (err, res) {
198+
expect(err).to.equal(null)
199+
expect(res.body).to.not.have.key('errors')
200+
expect(res.body.data.relationships.parent).to.be.an('object')
201+
expect(res.body.data.relationships.parent.data).to.equal(null)
202+
done()
203+
})
204+
})
205+
})
109206
})

test/hasManyPolymorphic.test.js

+56
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,60 @@ describe('loopback json api hasMany polymorphic relationships', function () {
104104
}
105105
)
106106
})
107+
108+
describe('Create relationship via API', function () {
109+
beforeEach(function (done) {
110+
Resource.create(
111+
{
112+
fileName: 'blah.jpg'
113+
},
114+
done
115+
)
116+
})
117+
118+
it(
119+
'should define a relationship to Resources when Post is created',
120+
function (done) {
121+
Resource.create(
122+
{
123+
fileName: 'blah.jpg'
124+
},
125+
function (err, resource) {
126+
expect(err).to.equal(null)
127+
request(app)
128+
.post('/posts')
129+
.send({
130+
data: {
131+
type: 'posts',
132+
attributes: {
133+
fileName: 'blah.jpg'
134+
},
135+
relationships: {
136+
resources: {
137+
data: [
138+
{
139+
id: 1,
140+
type: 'resources'
141+
}
142+
]
143+
}
144+
}
145+
}
146+
})
147+
.set('accept', 'application/vnd.api+json')
148+
.set('content-type', 'application/json')
149+
.expect(201)
150+
.end(function (err, res) {
151+
expect(err).to.equal(null)
152+
expect(res.body).to.not.have.key('errors')
153+
expect(res.body.data.relationships.resources).to.be.an(
154+
'object'
155+
)
156+
done()
157+
})
158+
}
159+
)
160+
}
161+
)
162+
})
107163
})

0 commit comments

Comments
 (0)