Fix Model.prototype.inspect
Return the raw object data when running on Node v0.11.14+ That way all `inspect` options are always preserved. When running on older version: - Honour the depth argument passed to the custom `inspect` function. - Disable color output, becase there is now way how to detect whether colors were enabled or disabled by the top-level caller.
This commit is contained in:
parent
9b759c95ac
commit
e4fc38788f
52
lib/model.js
52
lib/model.js
|
@ -53,14 +53,14 @@ function ModelBaseClass(data, options) {
|
|||
ModelBaseClass.prototype._initProperties = function (data, options) {
|
||||
var self = this;
|
||||
var ctor = this.constructor;
|
||||
|
||||
|
||||
if(data instanceof ctor) {
|
||||
// Convert the data to be plain object to avoid pollutions
|
||||
data = data.toObject(false);
|
||||
}
|
||||
var properties = _extend({}, ctor.definition.properties);
|
||||
data = data || {};
|
||||
|
||||
|
||||
if (typeof ctor.applyProperties === 'function') {
|
||||
ctor.applyProperties(data);
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
|
|||
if(strict === undefined) {
|
||||
strict = ctor.definition.settings.strict;
|
||||
}
|
||||
|
||||
|
||||
if (ctor.hideInternalProperties) {
|
||||
// Object.defineProperty() is expensive. We only try to make the internal
|
||||
// properties hidden (non-enumerable) if the model class has the
|
||||
|
@ -122,7 +122,7 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
|
|||
this.__strict = strict;
|
||||
this.__persisted = false;
|
||||
}
|
||||
|
||||
|
||||
if (options.persisted !== undefined) {
|
||||
this.__persisted = options.persisted === true;
|
||||
}
|
||||
|
@ -132,13 +132,13 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
|
|||
}
|
||||
|
||||
var keys = Object.keys(data);
|
||||
|
||||
|
||||
if (Array.isArray(options.fields)) {
|
||||
keys = keys.filter(function(k) {
|
||||
return (options.fields.indexOf(k) != -1);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var size = keys.length;
|
||||
var p, propVal;
|
||||
for (var k = 0; k < size; k++) {
|
||||
|
@ -156,7 +156,7 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
|
|||
}
|
||||
} else if (ctor.relations[p]) {
|
||||
var relationType = ctor.relations[p].type;
|
||||
|
||||
|
||||
if (!properties[p]) {
|
||||
var modelTo = ctor.relations[p].modelTo || ModelBaseClass;
|
||||
var multiple = ctor.relations[p].multiple;
|
||||
|
@ -165,7 +165,7 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
|
|||
properties[p] = { name: typeName, type: propType };
|
||||
this.setStrict(false);
|
||||
}
|
||||
|
||||
|
||||
// Relation
|
||||
if (relationType === 'belongsTo' && propVal != null) {
|
||||
// If the related model is populated
|
||||
|
@ -182,15 +182,15 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
keys = Object.keys(properties);
|
||||
|
||||
|
||||
if (Array.isArray(options.fields)) {
|
||||
keys = keys.filter(function(k) {
|
||||
return (options.fields.indexOf(k) != -1);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
size = keys.length;
|
||||
|
||||
for (k = 0; k < size; k++) {
|
||||
|
@ -216,11 +216,11 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
|
|||
self.__data[p] = def;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Handle complex types (JSON/Object)
|
||||
var type = properties[p].type;
|
||||
if (!BASE_TYPES[type.name]) {
|
||||
|
||||
|
||||
if (typeof self.__data[p] !== 'object' && self.__data[p]) {
|
||||
try {
|
||||
self.__data[p] = JSON.parse(self.__data[p] + '');
|
||||
|
@ -228,7 +228,7 @@ ModelBaseClass.prototype._initProperties = function (data, options) {
|
|||
self.__data[p] = String(self.__data[p]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (type.prototype instanceof ModelBaseClass) {
|
||||
if (!(self.__data[p] instanceof type)
|
||||
&& typeof self.__data[p] === 'object'
|
||||
|
@ -438,8 +438,28 @@ ModelBaseClass.prototype.reset = function () {
|
|||
}
|
||||
};
|
||||
|
||||
ModelBaseClass.prototype.inspect = function () {
|
||||
return util.inspect(this.__data, false, 4, true);
|
||||
// Node v0.11+ allows custom inspect functions to return an object
|
||||
// instead of string. That way options like `showHidden` and `colors`
|
||||
// can be preserved.
|
||||
var versionParts = process.versions.node
|
||||
.split(/\./g).map(function(v) { return +v; });
|
||||
|
||||
var INSPECT_SUPPORTS_OBJECT_RETVAL =
|
||||
versionParts[0] > 0 ||
|
||||
versionParts[1] > 11 ||
|
||||
(versionParts[0] === 11 && versionParts[1] >= 14);
|
||||
|
||||
ModelBaseClass.prototype.inspect = function (depth) {
|
||||
if (INSPECT_SUPPORTS_OBJECT_RETVAL)
|
||||
return this.__data;
|
||||
|
||||
// Workaround for older versions
|
||||
// See also https://github.com/joyent/node/commit/66280de133
|
||||
return util.inspect(this.__data, {
|
||||
showHidden: false,
|
||||
depth: depth,
|
||||
colors: false
|
||||
});
|
||||
};
|
||||
|
||||
ModelBaseClass.mixin = function (anotherClass, options) {
|
||||
|
|
|
@ -230,7 +230,7 @@ describe('validations', function () {
|
|||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should return validation metadata', function() {
|
||||
var expected = {name:[{validation: 'presence', options: {}}]};
|
||||
delete User.validations;
|
||||
|
@ -245,11 +245,11 @@ describe('validations', function () {
|
|||
|
||||
it('should validate presence', function () {
|
||||
User.validatesPresenceOf('name', 'email');
|
||||
|
||||
|
||||
var validations = User.validations;
|
||||
validations.name.should.eql([{validation: 'presence', options: {}}]);
|
||||
validations.email.should.eql([{validation: 'presence', options: {}}]);
|
||||
|
||||
|
||||
var u = new User;
|
||||
u.isValid().should.not.be.true;
|
||||
u.name = 1;
|
||||
|
@ -273,7 +273,7 @@ describe('validations', function () {
|
|||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('absence', function () {
|
||||
|
||||
it('should validate absence', function () {
|
||||
|
@ -355,7 +355,7 @@ describe('validations', function () {
|
|||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should skip blank values', function (done) {
|
||||
User.validatesUniquenessOf('email');
|
||||
var u = new User({email: ' '});
|
||||
|
@ -370,9 +370,9 @@ describe('validations', function () {
|
|||
});
|
||||
})).should.be.false;
|
||||
});
|
||||
|
||||
|
||||
it('should work with if/unless', function (done) {
|
||||
User.validatesUniquenessOf('email', {
|
||||
User.validatesUniquenessOf('email', {
|
||||
if: function() { return true; },
|
||||
unless: function() { return false; }
|
||||
});
|
||||
|
@ -414,7 +414,7 @@ describe('validations', function () {
|
|||
Boolean(u.isValid()).should.be.false;
|
||||
u.errors.codes.should.eql({ email: ['invalid-email'] });
|
||||
});
|
||||
|
||||
|
||||
it('should validate and return detailed error messages', function() {
|
||||
User.validate('global', function (err) {
|
||||
if (this.email === 'hello' || this.email === 'hey') {
|
||||
|
@ -427,11 +427,11 @@ describe('validations', function () {
|
|||
u.errors.should.eql({ email: ['Cannot be `hello`'] });
|
||||
u.errors.codes.should.eql({ email: ['invalid-email'] });
|
||||
});
|
||||
|
||||
|
||||
it('should validate using custom async validation', function(done) {
|
||||
User.validateAsync('email', function (err, next) {
|
||||
process.nextTick(next);
|
||||
}, {
|
||||
}, {
|
||||
if: function() { return true; },
|
||||
unless: function() { return false; }
|
||||
});
|
||||
|
@ -486,6 +486,14 @@ describe('validations', function () {
|
|||
.should.equal('`prop` is invalid (value: [ { a: [Object] } ]).');
|
||||
});
|
||||
|
||||
it('should exclude colors from Model values', function() {
|
||||
var obj = new User();
|
||||
obj.email = 'test@example.com';
|
||||
var err = givenValidationError('user', obj, 'is invalid');
|
||||
getErrorDetails(err).should.equal(
|
||||
'`user` is invalid (value: { email: \'test@example.com\' }).');
|
||||
});
|
||||
|
||||
function givenValidationError(propertyName, propertyValue, errorMessage) {
|
||||
var jsonVal = {};
|
||||
jsonVal[propertyName] = propertyValue;
|
||||
|
|
Loading…
Reference in New Issue