diff --git a/.npmignore b/.npmignore new file mode 100644 index 00000000..c08b3f46 --- /dev/null +++ b/.npmignore @@ -0,0 +1,10 @@ +node_modules +doc +coverage.html +coverage +v8.log + +.DS_Store +benchmark.js +analyse.r +docs/html diff --git a/lib/model.js b/lib/model.js index cacd6673..d1b50a1b 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2,6 +2,7 @@ * Module dependencies */ var util = require('util'); +var i8n = require('inflection'); var jutil = require('./jutil.js'); var Validatable = require('./validations.js').Validatable; var List = require('./list.js'); @@ -863,13 +864,29 @@ AbstractClass.prototype.reset = function () { * @example `User.hasMany(Post, {as: 'posts', foreignKey: 'authorId'});` */ AbstractClass.hasMany = function hasMany(anotherClass, params) { - var methodName = params.as; // or pluralize(anotherClass.modelName) - var fk = params.foreignKey; + var thisClass = this, thisClassName = this.modelName; + params = params || {}; + if (typeof anotherClass === 'string') { + params.as = anotherClass; + if (params.model) { + anotherClass = params.model; + } else { + var anotherClassName = i8n.singularize(anotherClass).toLowerCase(); + for(var name in this.schema.models) { + if (name.toLowerCase() === anotherClassName) { + anotherClass = this.schema.models[name]; + } + } + } + } + var methodName = params.as || + i8n.camelize(i8n.pluralize(anotherClass.modelName), true); + var fk = params.foreignKey || i8n.camelize(thisClassName + '_id', true); this.relations[params['as']] = { type: 'hasMany', keyFrom: 'id', - keyTo: params['foreignKey'], + keyTo: fk, modelTo: anotherClass, multiple: true }; diff --git a/package.json b/package.json index 258b6b08..7c42d37a 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,6 @@ "./docs/man/model.3", "./docs/man/hooks.3", "./docs/man/validations.3", - "./docs/man/jugglingdb.3", "./docs/man/roadmap.3", "./docs/man/changelog.3" ], @@ -71,5 +70,8 @@ "semicov": "*", "should": "~1.2.2", "mocha": "~1.8.2" + }, + "dependencies": { + "inflection": "~1.2.5" } } diff --git a/test/init.js b/test/init.js index 6d13dbec..99748e50 100644 --- a/test/init.js +++ b/test/init.js @@ -9,3 +9,11 @@ if (!process.env.TRAVIS) { require('semicov').init('lib'); } + +var Schema = require('../').Schema; + +if (!('getSchema' in global)) { + global.getSchema = function() { + return new Schema('memory'); + }; +} diff --git a/test/relations.test.js b/test/relations.test.js new file mode 100644 index 00000000..ed10dae7 --- /dev/null +++ b/test/relations.test.js @@ -0,0 +1,44 @@ +var db, Book, Chapter, Author, Reader; + +describe('relations', function() { + before(function() { + db = getSchema(); + Book = db.define('Book', {name: String}); + Chapter = db.define('Chapter', {name: String}); + Author = db.define('Author', {name: String}); + Reader = db.define('Reader', {name: String}); + }); + + after(function() { + db.disconnect(); + }); + + describe('hasMany', function() { + it('can be declared in different ways', function() { + Book.hasMany(Chapter); + Book.hasMany(Reader, {as: 'users'}); + Book.hasMany(Author, {foreignKey: 'projectId'}); + var b = new Book; + b.chapters.should.be.an.instanceOf(Function); + b.users.should.be.an.instanceOf(Function); + b.authors.should.be.an.instanceOf(Function); + Object.keys((new Chapter).toObject()).should.include('bookId'); + Object.keys((new Author).toObject()).should.include('projectId'); + }); + + it('can be declared in short form', function() { + Author.hasMany('readers'); + (new Author).readers.should.be.an.instanceOf(Function); + Object.keys((new Reader).toObject()).should.include('authorId'); + }); + }); + + describe('belongsTo', function() { + it('can be declared in different ways'); + it('can be declared in short form'); + }); + + describe('hasAndBelongsToMany', function() { + it('can be declared'); + }); +});