diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..b9ca117 Binary files /dev/null and b/.DS_Store differ diff --git a/lib/deserializer.js b/lib/deserializer.js index feb10a8..c4a18f6 100644 --- a/lib/deserializer.js +++ b/lib/deserializer.js @@ -1,6 +1,7 @@ 'use strict' var _ = require('lodash') +var utils = require('./utils') function defaultBeforeDeserialize (options, cb) { cb(null, options) @@ -78,6 +79,20 @@ function belongsToRelationships (options) { if (!relationship.data) { options.result[fkName] = null } else { + if (serverRelation.polymorphic) { + // Find the model which has a plural matching 'data.type' + // Allow case insensitive match + var relatedType = relationship.data.type.toLowerCase() + var modelName = _.findKey(model.app.models, function (model) { + var plural = utils.pluralForModel(model) + return plural.toLowerCase() === relatedType + }) + if (!modelName) { + return false + } + var discriminator = serverRelation.polymorphic.discriminator + options.result[discriminator] = modelName + } options.result[fkName] = relationship.data.id } }) diff --git a/lib/serializer.js b/lib/serializer.js index 0d355c1..4db9f5f 100644 --- a/lib/serializer.js +++ b/lib/serializer.js @@ -233,8 +233,12 @@ function parseRelations (data, relations, options) { var toType = '' if (relation.polymorphic && utils.relationFkOnModelFrom(relation)) { var discriminator = relation.polymorphic.discriminator - var model = options.app.models[data[discriminator]] - toType = utils.pluralForModel(model) + if (data.discriminator) { + var model = options.app.models[data[discriminator]] + if (model) { + toType = utils.pluralForModel(model) + } + } } else { toType = utils.pluralForModel(relation.modelTo) } diff --git a/test/belongsToPolymorphic.test.js b/test/belongsToPolymorphic.test.js index 7ab9c39..ff30961 100644 --- a/test/belongsToPolymorphic.test.js +++ b/test/belongsToPolymorphic.test.js @@ -106,4 +106,101 @@ describe('loopback json api belongsTo polymorphic relationships', function () { } ) }) + + describe('File with no relationship to a Post', function () { + beforeEach(function (done) { + FileModel.create( + { + fileName: 'blah.jpg' + }, + done + ) + }) + + it('should return a null value for relationship data', function (done) { + request(app).get('/fileModels/1').end(function (err, res) { + expect(err).to.equal(null) + expect(res.body).to.not.have.key('errors') + expect(res.body.data.relationships.parent).to.be.an('object') + expect(res.body.data.relationships.parent.data).to.equal(null) + done() + }) + }) + }) + + describe('Create relationship via API', function () { + beforeEach(function (done) { + Post.create( + { + title: 'Post One', + content: 'Content' + }, + done + ) + }) + + it('should define a relationship to Post when file is created', function ( + done + ) { + request(app) + .post('/fileModels') + .send({ + data: { + type: 'fileModels', + attributes: { + fileName: 'blah.jpg' + }, + relationships: { + parent: { + data: { + id: 1, + type: 'posts' + } + } + } + } + }) + .set('accept', 'application/vnd.api+json') + .set('content-type', 'application/json') + .expect(201) + .end(function (err, res) { + expect(err).to.equal(null) + expect(res.body).to.not.have.key('errors') + expect(res.body.data.relationships.parent).to.be.an('object') + expect(res.body.data.relationships.parent.data).to.be.an('object') + done() + }) + }) + + it('should ignore relationships with an invalid type', function (done) { + request(app) + .post('/fileModels') + .send({ + data: { + type: 'fileModels', + attributes: { + fileName: 'blah.jpg' + }, + relationships: { + parent: { + data: { + id: 1, + type: 'invalidType' + } + } + } + } + }) + .set('accept', 'application/vnd.api+json') + .set('content-type', 'application/json') + .expect(201) + .end(function (err, res) { + expect(err).to.equal(null) + expect(res.body).to.not.have.key('errors') + expect(res.body.data.relationships.parent).to.be.an('object') + expect(res.body.data.relationships.parent.data).to.equal(null) + done() + }) + }) + }) }) diff --git a/test/hasManyPolymorphic.test.js b/test/hasManyPolymorphic.test.js index 1264be0..056b1ad 100644 --- a/test/hasManyPolymorphic.test.js +++ b/test/hasManyPolymorphic.test.js @@ -104,4 +104,60 @@ describe('loopback json api hasMany polymorphic relationships', function () { } ) }) + + describe('Create relationship via API', function () { + beforeEach(function (done) { + Resource.create( + { + fileName: 'blah.jpg' + }, + done + ) + }) + + it( + 'should define a relationship to Resources when Post is created', + function (done) { + Resource.create( + { + fileName: 'blah.jpg' + }, + function (err, resource) { + expect(err).to.equal(null) + request(app) + .post('/posts') + .send({ + data: { + type: 'posts', + attributes: { + fileName: 'blah.jpg' + }, + relationships: { + resources: { + data: [ + { + id: 1, + type: 'resources' + } + ] + } + } + } + }) + .set('accept', 'application/vnd.api+json') + .set('content-type', 'application/json') + .expect(201) + .end(function (err, res) { + expect(err).to.equal(null) + expect(res.body).to.not.have.key('errors') + expect(res.body.data.relationships.resources).to.be.an( + 'object' + ) + done() + }) + } + ) + } + ) + }) })