diff --git a/examples/nesting-schema.js b/examples/nesting-schema.js new file mode 100644 index 00000000..36bccf96 --- /dev/null +++ b/examples/nesting-schema.js @@ -0,0 +1,21 @@ +var ModelBuilder = require('../../jugglingdb').ModelBuilder; +var modelBuilder = new ModelBuilder(); + +// simplier way to describe model +var User = modelBuilder.define('User', { + name: String, + bio: ModelBuilder.Text, + approved: Boolean, + joinedAt: Date, + age: Number, + address: { + street: String, + city: String, + state: String, + zipCode: String, + country: String + } +}); + +var user = new User({name: 'Joe', age: 20, address: {street: '123 Main St', 'city': 'San Jose', state: 'CA'}}); +console.log(user); diff --git a/lib/model-builder.js b/lib/model-builder.js index 1962d74f..18acd3fd 100644 --- a/lib/model-builder.js +++ b/lib/model-builder.js @@ -107,10 +107,13 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett properties = properties || {}; settings = settings || {}; - buildSchema(className, properties); + this.buildSchema(className, properties); // every class can receive hash of data as optional param - var ModelClass = function ModelConstructor(data, schema) { + var ModelClass = function ModelConstructor(data, schema) { + if(!(this instanceof ModelConstructor)) { + return new ModelConstructor(data, schema); + } ModelBaseClass.apply(this, arguments); if(!this.schema) { hiddenProperty(this, 'schema', schema || this.constructor.schema); @@ -413,13 +416,13 @@ function defineReadonlyProp(obj, key, value) { * @param type The type string, such as 'number', 'Number', 'boolean', or 'String'. It's case insensitive * @returns {Function} if the type is resolved */ -function getSchemaType(type) { +ModelBuilder.prototype.getSchemaType = function(type) { if (!type) { return type; } if (Array.isArray(type) && type.length > 0) { // For array types, the first item should be the type string - var itemType = getSchemaType(type[0]); + var itemType = this.getSchemaType(type[0]); if (typeof itemType === 'function') { return [itemType]; } @@ -435,10 +438,16 @@ function getSchemaType(type) { } else if (type.constructor.name == 'Object') { // We also support the syntax {type: 'string', ...} if (type.type) { - return getSchemaType(type.type); + return this.getSchemaType(type.type); } else { + if(!this.anonymousTypesCount) { + this.anonymousTypesCount = 1; + } + return this.define('AnonymousType' + this.anonymousTypesCount, type, {idInjection: false}); + /* console.error(type); throw new Error('Missing type property'); + */ } } else if('function' === typeof type ) { return type; @@ -453,10 +462,10 @@ function getSchemaType(type) { * @param associations An array of associations between models * @returns {*} */ -function buildSchema(name, properties, associations) { +ModelBuilder.prototype.buildSchema = function(name, properties, associations) { for (var p in properties) { // console.log(name + "." + p + ": " + properties[p]); - var type = getSchemaType(properties[p]); + var type = this.getSchemaType(properties[p]); if (typeof type === 'string') { // console.log('Association: ' + type); if (Array.isArray(associations)) { @@ -512,7 +521,7 @@ ModelBuilder.prototype.buildModels = function (schemas) { var associations = []; for (var s in schemas) { var name = schemas[s].name; - var schema = buildSchema(name, schemas[s].properties, associations); + var schema = this.buildSchema(name, schemas[s].properties, associations); var model = this.define(name, schema, schemas[s].options); models[name] = model; } diff --git a/test/adl.test.js b/test/adl.test.js index 5a83edfd..1c1f4c4c 100644 --- a/test/adl.test.js +++ b/test/adl.test.js @@ -38,6 +38,49 @@ describe('ModelBuilder define model', function () { done(null, User); }); + + it('should be able to define nesting models', function (done) { + var modelBuilder = new ModelBuilder(); + + // simplier way to describe model + var User = modelBuilder.define('User', { + name: String, + bio: ModelBuilder.Text, + approved: Boolean, + joinedAt: Date, + age: Number, + address: { + street: String, + city: String, + state: String, + zipCode: String, + country: String + } + }); + + // define any custom method + User.prototype.getNameAndAge = function () { + return this.name + ', ' + this.age; + }; + + modelBuilder.models.should.be.a('object').and.have.property('User', User); + modelBuilder.definitions.should.be.a('object').and.have.property('User'); + + var user = new User({name: 'Joe', age: 20, address: {street: '123 Main St', 'city': 'San Jose', state: 'CA'}}); + console.log(user); + + User.modelName.should.equal('User'); + user.should.be.a('object').and.have.property('name', 'Joe'); + user.should.have.property('name', 'Joe'); + user.should.have.property('age', 20); + user.should.not.have.property('bio'); + user.should.have.property('address'); + user.address.should.have.property('city', 'San Jose'); + user.address.should.have.property('state', 'CA'); + done(null, User); + }); + + });