diff --git a/lib/common/util.js b/lib/common/util.js index b2bcf41c949..f7c11ffbe7d 100644 --- a/lib/common/util.js +++ b/lib/common/util.js @@ -203,6 +203,22 @@ function getType(value) { return Object.prototype.toString.call(value).match(/\s(\w+)\]/)[1]; } +/** + * Assign a value to a property in an Array iterator. + * + * @param {string} prop - Name of the property to assign to the object. + * @param {*} value - Value of the property. + * @return {function} + */ +function propAssign(prop, value) { + return function(obj) { + obj[prop] = value; + return obj; + }; +} + +module.exports.propAssign = propAssign; + /** * Check if an object is of the given type. * diff --git a/lib/datastore/request.js b/lib/datastore/request.js index 0ca5561ccef..a397936d8b3 100644 --- a/lib/datastore/request.js +++ b/lib/datastore/request.js @@ -147,6 +147,14 @@ DatastoreRequest.prototype.get = function(keys, callback) { }); }; +/** + * Maps to {module:datastore/dataset#save}, forcing the method to be `insert`. + */ +DatastoreRequest.prototype.insert = function(entities, callback) { + entities = util.arrayize(entities).map(util.propAssign('method', 'insert')); + this.save(entities, callback); +}; + /** * Insert or update the specified object(s). If a key is incomplete, its * associated object is inserted and the original Key object is updated to @@ -243,8 +251,7 @@ DatastoreRequest.prototype.get = function(keys, callback) { * ], function(err) {}); */ DatastoreRequest.prototype.save = function(entities, callback) { - var isMultipleRequest = Array.isArray(entities); - entities = isMultipleRequest ? entities : [entities]; + entities = util.arrayize(entities); var insertIndexes = []; @@ -346,14 +353,11 @@ DatastoreRequest.prototype.save = function(entities, callback) { * ], function(err) {}); */ DatastoreRequest.prototype.delete = function(keys, callback) { - var isMultipleRequest = Array.isArray(keys); - keys = isMultipleRequest ? keys : [keys]; - callback = callback || util.noop; var req = { mutation: { - delete: keys.map(entity.keyToKeyProto) + delete: util.arrayize(keys).map(entity.keyToKeyProto) } }; @@ -527,6 +531,22 @@ DatastoreRequest.prototype.allocateIds = function(incompleteKey, n, callback) { }); }; +/** + * Maps to {module:datastore/dataset#save}, forcing the method to be `update`. + */ +DatastoreRequest.prototype.update = function(entities, callback) { + entities = util.arrayize(entities).map(util.propAssign('method', 'update')); + this.save(entities, callback); +}; + +/** + * Maps to {module:datastore/dataset#save}, forcing the method to be `upsert`. + */ +DatastoreRequest.prototype.upsert = function(entities, callback) { + entities = util.arrayize(entities).map(util.propAssign('method', 'upsert')); + this.save(entities, callback); +}; + /** * Make a request to the API endpoint. Properties to indicate a transactional or * non-transactional operation are added automatically. diff --git a/test/common/util.js b/test/common/util.js index b8fd7348c0d..b648a3cfdfd 100644 --- a/test/common/util.js +++ b/test/common/util.js @@ -437,4 +437,12 @@ describe('common/util', function() { }); }); }); + + describe('propAssign', function() { + it('should assign a property and value to an object', function() { + var obj = {}; + util.propAssign('prop', 'value')(obj); + assert.equal(obj.prop, 'value'); + }); + }); }); diff --git a/test/datastore/request.js b/test/datastore/request.js index 3d49b668a69..deef8e8bf03 100644 --- a/test/datastore/request.js +++ b/test/datastore/request.js @@ -142,6 +142,26 @@ describe('Request', function() { }); }); + describe('insert', function() { + it('should pass the correct arguments to save', function(done) { + request.save = function(entities, callback) { + assert.deepEqual(entities, [{ + key: { + namespace: 'ns', + path: ['Company'], + }, + data: {}, + method: 'insert' + }]); + + callback(); + }; + + var key = new entity.Key({ namespace: 'ns', path: ['Company'] }); + request.insert({ key: key, data: {} }, done); + }); + }); + describe('save', function() { it('should save with incomplete key', function(done) { request.makeReq_ = function(method, req, callback) { @@ -461,6 +481,46 @@ describe('Request', function() { }); }); + describe('update', function() { + it('should pass the correct arguments to save', function(done) { + request.save = function(entities, callback) { + assert.deepEqual(entities, [{ + key: { + namespace: 'ns', + path: ['Company'], + }, + data: {}, + method: 'update' + }]); + + callback(); + }; + + var key = new entity.Key({ namespace: 'ns', path: ['Company'] }); + request.update({ key: key, data: {} }, done); + }); + }); + + describe('upsert', function() { + it('should pass the correct arguments to save', function(done) { + request.save = function(entities, callback) { + assert.deepEqual(entities, [{ + key: { + namespace: 'ns', + path: ['Company'], + }, + data: {}, + method: 'upsert' + }]); + + callback(); + }; + + var key = new entity.Key({ namespace: 'ns', path: ['Company'] }); + request.upsert({ key: key, data: {} }, done); + }); + }); + describe('allocateIds', function() { it('should produce proper allocate IDs req protos', function(done) { request.makeReq_ = function(method, req, callback) {