diff --git a/lib/datastore/dataset.js b/lib/datastore/dataset.js index ed0e71b3db8..bd332d3380e 100644 --- a/lib/datastore/dataset.js +++ b/lib/datastore/dataset.js @@ -107,6 +107,10 @@ function Dataset(options) { * * You may also specify a configuration object to define a namespace and path. * + * Once you have created a Key object, all properties (namespace, path, and id) + * are read-only. You can access them from the returned Key object: `key.id`, + * `key.namespace`, and `key.path` will return their respective components. + * * @example * var key; * diff --git a/lib/datastore/entity.js b/lib/datastore/entity.js index c73c042836c..df035e25f24 100644 --- a/lib/datastore/entity.js +++ b/lib/datastore/entity.js @@ -62,7 +62,8 @@ var SIGN_TO_ORDER = { }; /** - * Build a Datastore Key object. + * Build a Datastore Key object. Keys components should only be specified during + * instantiation. They are read-only via properties on the returned Key object. * * @constructor * @param {object} - Configuration object. @@ -74,10 +75,25 @@ var SIGN_TO_ORDER = { * namespace: 'ns', * path: ['Company', 123] * }); + * + * // key.id = 123 + * // key.namespace = 'ns' + * // key.path = ['Company', 123] */ function Key(options) { this.namespace_ = options.namespace; this.path_ = options.path; + this.id_ = options.path[options.path.length - 1]; + + Object.defineProperties(this, + ['namespace', 'path', 'id'].reduce(function(acc, key) { + acc[key] = { + value: this[key + '_'], + writable: false + }; + return acc; + }.bind(this), {}) + ); } module.exports.Key = Key; diff --git a/test/datastore/entity.js b/test/datastore/entity.js index f3a789b3677..4e520280737 100644 --- a/test/datastore/entity.js +++ b/test/datastore/entity.js @@ -120,6 +120,28 @@ var queryFilterProto = { group_by: [] }; +describe('Key', function() { + var path = ['Kind', 23]; + var id = path[path.length - 1]; + var key = new entity.Key({ + path: ['Kind', 23] + }); + + it('should expose internal Key values', function() { + assert.strictEqual(key.namespace, undefined); + assert.deepEqual(key.path, path); + assert.equal(key.id, id); + }); + + it('should protect internal Key values', function() { + ['namespace', 'path', 'id'].forEach(function(property) { + assert.throws(function() { + key[property] = 'overriden value'; + }, /Cannot assign/); + }); + }); +}); + describe('registerKind', function() { it('should be able to register valid field metadata', function(done) { entity.registerKind('namespace', 'kind', blogPostMetadata);