diff --git a/lib/model.js b/lib/model.js index 1981cda9..6438585f 100644 --- a/lib/model.js +++ b/lib/model.js @@ -432,8 +432,9 @@ Model.belongsToRemoting = function(relationName, relation, define) { }; Model.hasOneRemoting = function(relationName, relation, define) { - var fn = this.prototype[relationName]; var pathName = (relation.options.http && relation.options.http.path) || relationName; + var toModelName = relation.modelTo.modelName; + define('__get__' + relationName, { isStatic: false, http: {verb: 'get', path: '/' + pathName}, @@ -441,7 +442,33 @@ Model.hasOneRemoting = function(relationName, relation, define) { description: 'Fetches hasOne relation ' + relationName, accessType: 'READ', returns: {arg: relationName, type: relation.modelTo.modelName, root: true} - }, fn); + }); + + define('__create__' + relationName, { + isStatic: false, + http: {verb: 'post', path: '/' + pathName}, + accepts: {arg: 'data', type: toModelName, http: {source: 'body'}}, + description: 'Creates a new instance in ' + relationName + ' of this model.', + accessType: 'WRITE', + returns: {arg: 'data', type: toModelName, root: true} + }); + + define('__update__' + relationName, { + isStatic: false, + http: {verb: 'put', path: '/' + pathName}, + accepts: {arg: 'data', type: toModelName, http: {source: 'body'}}, + description: 'Update ' + relationName + ' of this model.', + accessType: 'WRITE', + returns: {arg: 'data', type: toModelName, root: true} + }); + + define('__destroy__' + relationName, { + isStatic: false, + http: {verb: 'delete', path: '/' + pathName}, + description: 'Deletes ' + relationName + ' of this model.', + accessType: 'WRITE' + }); + }; Model.hasManyRemoting = function(relationName, relation, define) { diff --git a/test/fixtures/simple-integration-app/models.json b/test/fixtures/simple-integration-app/models.json index 6f4e7535..af1cd590 100644 --- a/test/fixtures/simple-integration-app/models.json +++ b/test/fixtures/simple-integration-app/models.json @@ -114,5 +114,32 @@ } } } + }, + "customer": { + "base": "PersistedModel", + "dataSource": "db", + "public": true, + "properties": { + "name": { + "type": "string", + "required": true + } + }, + "relations": { + "profile": { + "type": "hasOne", + "model": "profile" + } + } + }, + "profile": { + "base": "PersistedModel", + "dataSource": "db", + "public": true, + "properties": { + "points": { + "type": "number" + } + } } } diff --git a/test/relations.integration.js b/test/relations.integration.js index b268577c..1abb3c58 100644 --- a/test/relations.integration.js +++ b/test/relations.integration.js @@ -1360,4 +1360,96 @@ describe('relations - integration', function() { }); }); + describe('hasOne', function() { + var cust; + + before(function createCustomer(done) { + var test = this; + app.models.customer.create({ name: 'John' }, function(err, c) { + if (err) { + return done(err); + } + cust = c; + done(); + }); + }); + + after(function(done) { + var self = this; + this.app.models.customer.destroyAll(function(err) { + if (err) { + return done(err); + } + self.app.models.profile.destroyAll(done); + }); + }); + + it('should create the referenced model', function(done) { + var url = '/api/customers/' + cust.id + '/profile'; + + this.post(url) + .send({points: 10}) + .expect(200, function(err, res) { + if (err) { + return done(err); + } + expect(res.body.points).to.be.eql(10); + expect(res.body.customerId).to.be.eql(cust.id); + done(); + }); + }); + + it('should find the referenced model', function(done) { + var url = '/api/customers/' + cust.id + '/profile'; + this.get(url) + .expect(200, function(err, res) { + if (err) { + return done(err); + } + expect(res.body.points).to.be.eql(10); + expect(res.body.customerId).to.be.eql(cust.id); + done(); + }); + }); + + it('should not create the referenced model twice', function(done) { + var url = '/api/customers/' + cust.id + '/profile'; + this.post(url) + .send({points: 20}) + .expect(500, function(err, res) { + done(err); + }); + }); + + it('should update the referenced model', function(done) { + var url = '/api/customers/' + cust.id + '/profile'; + this.put(url) + .send({points: 100}) + .expect(200, function(err, res) { + if (err) { + return done(err); + } + expect(res.body.points).to.be.eql(100); + expect(res.body.customerId).to.be.eql(cust.id); + done(); + }); + }); + + it('should delete the referenced model', function(done) { + var url = '/api/customers/' + cust.id + '/profile'; + this.del(url) + .expect(204, function(err, res) { + done(err); + }); + }); + + it('should not find the referenced model', function(done) { + var url = '/api/customers/' + cust.id + '/profile'; + this.get(url) + .expect(404, function(err, res) { + done(err); + }); + }); + }); + });