Permalink
Browse files

populate works with String & Number _ids

closes #568
  • Loading branch information...
1 parent 282a167 commit 692279973f43530a02232fd89b21eaed74889382 @aheckmann aheckmann committed Oct 19, 2011
Showing with 108 additions and 46 deletions.
  1. +5 −2 lib/schema/number.js
  2. +2 −41 lib/schema/objectid.js
  3. +3 −2 lib/schema/string.js
  4. +26 −1 lib/schematype.js
  5. +72 −0 test/model.ref.test.js
@@ -16,7 +16,7 @@ var SchemaType = require('../schematype')
*/
function SchemaNumber (key, options) {
- SchemaType.call(this, key, options);
+ SchemaType.call(this, key, options, 'Number');
};
/**
@@ -81,7 +81,9 @@ SchemaNumber.prototype.max = function (value, message) {
* @api private
*/
-SchemaNumber.prototype.cast = function (value, doc) {
+SchemaNumber.prototype.cast = function (value, doc, init) {
+ if (SchemaType._isRef(this, value, init)) return value;
+
if (!isNaN(value)){
if (null === value) return value;
if ('' === value) return null;
@@ -90,6 +92,7 @@ SchemaNumber.prototype.cast = function (value, doc) {
(value.toString && value.toString() == Number(value)))
return new MongooseNumber(value, this.path, doc);
}
+
throw new CastError('number', value);
};
@@ -17,7 +17,7 @@ var SchemaType = require('../schematype')
*/
function ObjectId (key, options) {
- SchemaType.call(this, key, options);
+ SchemaType.call(this, key, options, 'ObjectID');
};
/**
@@ -37,40 +37,6 @@ ObjectId.prototype.checkRequired = function (value) {
};
/**
- * Overrides the getters application for the population special-case
- *
- * @param {Object} value
- * @param {Object} scope
- * @api private
- */
-
-ObjectId.prototype.applyGetters = function (value, scope) {
- if (this.options.ref && value && value._id && value._id instanceof oid) {
- // means the object id was populated
- return value;
- }
-
- return SchemaType.prototype.applyGetters.call(this, value, scope);
-};
-
-/**
- * Overrides the getters application for the population special-case
- *
- * @param {Object} value
- * @param {Object} scope
- * @api private
- */
-
-ObjectId.prototype.applySetters = function (value, scope) {
- if (this.options.ref && value && value._id && value._id instanceof oid) {
- // means the object id was populated
- return value;
- }
-
- return SchemaType.prototype.applySetters.call(this, value, scope);
-};
-
-/**
* Casts to ObjectId
*
* @param {Object} value
@@ -80,12 +46,7 @@ ObjectId.prototype.applySetters = function (value, scope) {
*/
ObjectId.prototype.cast = function (value, scope, init) {
- if (this.options
- && this.options.ref
- && init) {
- if (null == value) return value;
- if (value && value._id && value._id instanceof oid) return value;
- }
+ if (SchemaType._isRef(this, value, init)) return value;
if (value === null) return value;
@@ -16,7 +16,7 @@ var SchemaType = require('../schematype')
function SchemaString (key, options) {
this.enumValues = [];
this.regExp = null;
- SchemaType.call(this, key, options);
+ SchemaType.call(this, key, options, 'String');
};
/**
@@ -125,7 +125,8 @@ SchemaString.prototype.checkRequired = function (v) {
* @api private
*/
-SchemaString.prototype.cast = function (value) {
+SchemaString.prototype.cast = function (value, scope, init) {
+ if (SchemaType._isRef(this, value, init)) return value;
if (value === null) return value;
if ('undefined' !== typeof value && value.toString) return value.toString();
throw new CastError('string', value);
View
@@ -13,8 +13,9 @@ var utils = require('./utils');
* @api public
*/
-function SchemaType (path, options) {
+function SchemaType (path, options, instance) {
this.path = path;
+ this.instance = instance;
this.validators = [];
this.setters = [];
this.getters = [];
@@ -199,6 +200,8 @@ SchemaType.prototype.getDefault = function (scope) {
*/
SchemaType.prototype.applySetters = function (value, scope, init) {
+ if (SchemaType._isRef(this, value, init)) return value;
+
var v = value
, setters = this.setters
, len = setters.length;
@@ -229,6 +232,8 @@ SchemaType.prototype.applySetters = function (value, scope, init) {
*/
SchemaType.prototype.applyGetters = function (value, scope) {
+ if (SchemaType._isRef(this, value, true)) return value;
+
var v = value
, getters = this.getters
, len = getters.length;
@@ -291,6 +296,26 @@ SchemaType.prototype.doValidate = function (value, fn, scope) {
};
/**
+ * Determines if value is a valid Reference.
+ *
+ * @param {SchemaType} self
+ * @param {object} value
+ * @param {Boolean} init
+ * @param {MongooseType} instance
+ * @return Boolean
+ * @private
+ */
+
+SchemaType._isRef = function (self, value, init) {
+ if (self.options && self.options.ref && init) {
+ if (null == value) return true;
+ if (value._id && value._id.constructor.name === self.instance) return true;
+ }
+
+ return false;
+}
+
+/**
* Schema validator error
*
* @param {String} path
@@ -1113,6 +1113,78 @@ module.exports = {
bp._creator.should.be.an.instanceof(DocObjectId);
bp.set('_creator', new DocObjectId().toString());
bp._creator.should.be.an.instanceof(DocObjectId);
+ },
+
+ 'populate should work on String _ids': function () {
+ var db = start();
+
+ var UserSchema = new Schema({
+ _id: String
+ , name: String
+ })
+
+ var NoteSchema = new Schema({
+ author: { type: String, ref: 'UserWithStringId' }
+ , body: String
+ })
+
+ var User = db.model('UserWithStringId', UserSchema, random())
+ var Note = db.model('NoteWithStringId', NoteSchema, random())
+
+ var alice = new User({_id: 'alice', name: "Alice"})
+
+ alice.save(function (err) {
+ should.strictEqual(err, null);
+
+ var note = new Note({author: 'alice', body: "Buy Milk"});
+ note.save(function (err) {
+ should.strictEqual(err, null);
+
+ Note.findById(note.id).populate('author').run(function (err, note) {
+ db.close();
+ should.strictEqual(err, null);
+ note.body.should.equal('Buy Milk');
+ should.exist(note.author);
+ note.author.name.should.equal('Alice');
+ });
+ });
+ })
+ },
+
+ 'populate should work on Number _ids': function () {
+ var db = start();
+
+ var UserSchema = new Schema({
+ _id: Number
+ , name: String
+ })
+
+ var NoteSchema = new Schema({
+ author: { type: Number, ref: 'UserWithNumberId' }
+ , body: String
+ })
+
+ var User = db.model('UserWithNumberId', UserSchema, random())
+ var Note = db.model('NoteWithNumberId', NoteSchema, random())
+
+ var alice = new User({_id: 2359, name: "Alice"})
+
+ alice.save(function (err) {
+ should.strictEqual(err, null);
+
+ var note = new Note({author: 2359, body: "Buy Milk"});
+ note.save(function (err) {
+ should.strictEqual(err, null);
+
+ Note.findById(note.id).populate('author').run(function (err, note) {
+ db.close();
+ should.strictEqual(err, null);
+ note.body.should.equal('Buy Milk');
+ should.exist(note.author);
+ note.author.name.should.equal('Alice');
+ });
+ });
+ })
}
};

0 comments on commit 6922799

Please sign in to comment.