Make sure own properties are copied by toObject for non-strict mode
See https://github.com/strongloop/loopback/issues/162
This commit is contained in:
parent
38e31b3033
commit
ee5b351398
27
lib/model.js
27
lib/model.js
|
@ -199,16 +199,20 @@ ModelBaseClass.toString = function () {
|
||||||
/**
|
/**
|
||||||
* Convert instance to Object
|
* Convert instance to Object
|
||||||
*
|
*
|
||||||
* @param {Boolean} onlySchema - restrict properties to dataSource only, default false
|
* @param {Boolean} onlySchema - restrict properties to dataSource only, default true
|
||||||
* when onlySchema == true, only properties defined in dataSource returned,
|
* when onlySchema == true, only properties defined in dataSource returned,
|
||||||
* otherwise all enumerable properties returned
|
* otherwise all enumerable properties returned
|
||||||
* @returns {Object} - canonical object representation (no getters and setters)
|
* @returns {Object} - canonical object representation (no getters and setters)
|
||||||
*/
|
*/
|
||||||
ModelBaseClass.prototype.toObject = function (onlySchema) {
|
ModelBaseClass.prototype.toObject = function (onlySchema) {
|
||||||
|
if(onlySchema === undefined) {
|
||||||
|
onlySchema = true;
|
||||||
|
}
|
||||||
var data = {};
|
var data = {};
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var schemaLess = this.constructor.definition.settings.strict === false || !onlySchema;
|
var strict = this.constructor.definition.settings.strict;
|
||||||
|
var schemaLess = strict === false || !onlySchema;
|
||||||
this.constructor.forEachProperty(function (propertyName) {
|
this.constructor.forEachProperty(function (propertyName) {
|
||||||
if (self[propertyName] instanceof List) {
|
if (self[propertyName] instanceof List) {
|
||||||
data[propertyName] = self[propertyName].toObject(!schemaLess);
|
data[propertyName] = self[propertyName].toObject(!schemaLess);
|
||||||
|
@ -223,10 +227,25 @@ ModelBaseClass.prototype.toObject = function (onlySchema) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var val = null;
|
||||||
if (schemaLess) {
|
if (schemaLess) {
|
||||||
for (var propertyName in self.__data) {
|
// Find its own properties which can be set via myModel.myProperty = 'myValue'.
|
||||||
|
// If the property is not declared in the model definition, no setter will be
|
||||||
|
// triggered to add it to __data
|
||||||
|
for (var propertyName in self) {
|
||||||
|
if(self.hasOwnProperty(propertyName) && (!data.hasOwnProperty(propertyName))) {
|
||||||
|
val = self[propertyName];
|
||||||
|
if (val !== undefined && val !== null && val.toObject) {
|
||||||
|
data[propertyName] = val.toObject(!schemaLess);
|
||||||
|
} else {
|
||||||
|
data[propertyName] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Now continue to check __data
|
||||||
|
for (propertyName in self.__data) {
|
||||||
if (!data.hasOwnProperty(propertyName)) {
|
if (!data.hasOwnProperty(propertyName)) {
|
||||||
var val = self.hasOwnProperty(propertyName) ? self[propertyName] : self.__data[propertyName];
|
val = self.hasOwnProperty(propertyName) ? self[propertyName] : self.__data[propertyName];
|
||||||
if (val !== undefined && val !== null && val.toObject) {
|
if (val !== undefined && val !== null && val.toObject) {
|
||||||
data[propertyName] = val.toObject(!schemaLess);
|
data[propertyName] = val.toObject(!schemaLess);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -54,6 +54,26 @@ describe('ModelBuilder define model', function () {
|
||||||
done(null, User);
|
done(null, User);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should ignore non-predefined properties in strict mode', function (done) {
|
||||||
|
var modelBuilder = new ModelBuilder();
|
||||||
|
|
||||||
|
var User = modelBuilder.define('User', {name: String, bio: String}, {strict: true});
|
||||||
|
|
||||||
|
var user = new User({name: 'Joe'});
|
||||||
|
user.age = 10;
|
||||||
|
user.bio = 'me';
|
||||||
|
|
||||||
|
assert(user.name === 'Joe');
|
||||||
|
assert(user.bio === 'me');
|
||||||
|
assert(user.toObject().age === undefined);
|
||||||
|
assert(user.toObject(true).age === undefined);
|
||||||
|
assert(user.toObject(false).age === 10);
|
||||||
|
assert(user.toObject().bio === 'me');
|
||||||
|
assert(user.toObject(true).bio === 'me');
|
||||||
|
assert(user.toObject(false).bio === 'me');
|
||||||
|
done(null, User);
|
||||||
|
});
|
||||||
|
|
||||||
it('should throw when unknown properties are used if strict=throw', function (done) {
|
it('should throw when unknown properties are used if strict=throw', function (done) {
|
||||||
var modelBuilder = new ModelBuilder();
|
var modelBuilder = new ModelBuilder();
|
||||||
|
|
||||||
|
@ -83,6 +103,26 @@ describe('ModelBuilder define model', function () {
|
||||||
done(null, User);
|
done(null, User);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should take non-predefined properties in non-strict mode', function (done) {
|
||||||
|
var modelBuilder = new ModelBuilder();
|
||||||
|
|
||||||
|
var User = modelBuilder.define('User', {name: String, bio: String}, {strict: false});
|
||||||
|
|
||||||
|
var user = new User({name: 'Joe'});
|
||||||
|
user.age = 10;
|
||||||
|
user.bio = 'me';
|
||||||
|
|
||||||
|
assert(user.name === 'Joe');
|
||||||
|
assert(user.bio === 'me');
|
||||||
|
assert(user.toObject().age === 10);
|
||||||
|
assert(user.toObject(false).age === 10);
|
||||||
|
assert(user.toObject(true).age === 10);
|
||||||
|
assert(user.toObject().bio === 'me');
|
||||||
|
assert(user.toObject(true).bio === 'me');
|
||||||
|
assert(user.toObject(false).bio === 'me');
|
||||||
|
done(null, User);
|
||||||
|
});
|
||||||
|
|
||||||
it('should use false as the default value for strict', function (done) {
|
it('should use false as the default value for strict', function (done) {
|
||||||
var modelBuilder = new ModelBuilder();
|
var modelBuilder = new ModelBuilder();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue