Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 46 additions & 47 deletions lib/hasAndBelongsToMany.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ var mongoose = require('mongoose')
, MongooseArray = mongoose.Types.Array
, i = require('i')()
, utils = require('./utils')
, merge = utils.merge;
, merge = utils.merge
, HasAndBelongsToMany
, associate;

module.exports = function hasAndBelongsToMany (schema, model, options) {
module.exports = function hasAndBelongsToMany (schema, associationName, options) {
this.type = 'habtm';

this.schema = schema;
this.model = model;
this.options = options || {};

this.pathName = this.options.through || i.pluralize(this.model.toLowerCase());
this.pathName = associationName;
this.model = this.options.modelName || i.classify(associationName);

var path = {};
path[this.pathName] = [{ type: ObjectId, index: true, ref: this.model }];
Expand Down Expand Up @@ -40,12 +41,11 @@ module.exports = function hasAndBelongsToMany (schema, model, options) {
};
};

/* Builds the instance of the child element
*
* @param {Object|Array} objs
* @return {Document|Array}
* @api public
*/
// Builds the instance of the child element
//
// @param {Object|Array} objs
// @return {Document|Array}
// @api public

MongooseArray.prototype.build = function (objs) {
var childModelName = this._schema.options.relationshipModel;
Expand Down Expand Up @@ -84,12 +84,11 @@ MongooseArray.prototype.build = function (objs) {
}
};

/* Create a child document and add it to the parent `Array`
*
* @param {Object|Array} objs [object(s) to create]
* @param {Functions} callback [passed: (err, parent, created children)]
* @api public
*/
// Create a child document and add it to the parent `Array`
//
// @param {Object|Array} objs [object(s) to create]
// @param {Functions} callback [passed: (err, parent, created children)]
// @api public

MongooseArray.prototype.create = function (objs, callback) {
objs = this.build(objs);
Expand Down Expand Up @@ -151,12 +150,12 @@ MongooseArray.prototype.create = function (objs, callback) {
}
};

/* Append an already instantiated document saves it in the process.
*
* @param {Document} child
* @param {Function} callback
* @api public
*/
// Append an already instantiated document saves it in the process.
//
// @param {Document} child
// @param {Function} callback
// @api public

MongooseArray.prototype.append = function (child, callback) {

// start remove me asap
Expand Down Expand Up @@ -194,12 +193,12 @@ MongooseArray.prototype.append = function (child, callback) {
return child;
};

/* Append many instantiated children documents
*
* @param {Array} children
* @param {Function} callback
* @api public
*/
// Append many instantiated children documents
//
// @param {Array} children
// @param {Function} callback
// @api public

MongooseArray.prototype._concat = MongooseArray.prototype.concat;
MongooseArray.prototype.concat = function (docs, callback) {
var throwErr = utils.throwErr(callback);
Expand Down Expand Up @@ -232,10 +231,10 @@ MongooseArray.prototype.concat = function (docs, callback) {

};

/* Find children documents
*
* *This is a copy of Model.find w/ added error throwing and such*
*/
// Find children documents

// *This is a copy of Model.find w/ added error throwing and such*

MongooseArray.prototype.find = function (conditions, fields, options, callback) {
// Copied from `Model.find`
if ('function' == typeof conditions) {
Expand Down Expand Up @@ -290,13 +289,13 @@ MongooseArray.prototype.find = function (conditions, fields, options, callback)
return query;
};

/* Syntactic sugar to populate the array
*
* @param {Array} fields
* @param {Function} callback
* @return {Query}
* @api public
*/
// Syntactic sugar to populate the array

// @param {Array} fields
// @param {Function} callback
// @return {Query}
// @api public

MongooseArray.prototype.populate = function (fields, callback) {
if ('function' == typeof fields) {
callback = fields;
Expand All @@ -310,13 +309,13 @@ MongooseArray.prototype.populate = function (fields, callback) {
.exec(callback);
};

/* Overrides MongooseArray.remove only for dependent:destroy relationships
*
* @param {ObjectId} id
* @param {Function} callback
* @return {ObjectId}
* @api public
*/
// Overrides MongooseArray.remove only for dependent:destroy relationships

// @param {ObjectId} id
// @param {Function} callback
// @return {ObjectId}
// @api public

MongooseArray.prototype._remove = MongooseArray.prototype.remove;
MongooseArray.prototype.remove = MongooseArray.prototype.delete = function (id, callback) {
var parent = this._parent,
Expand Down
5 changes: 1 addition & 4 deletions lib/hasMany.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@ function associate (objects) {
};

function HasMany (doc, options) {
options = options || {};
this._options = options;
this._options = options || {};

this.as = this._options.as;
this.inverse_of = this.inverse_of;
Expand All @@ -72,8 +71,6 @@ function HasMany (doc, options) {
}

HasMany.prototype.build = function(objects){
var Model;

if(Array.isArray(objects)){
return objects.map(function(object){
return this.build(object);
Expand Down
24 changes: 13 additions & 11 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@

module.exports = exports = function mongoRelations (mongoose) {
var Schema = mongoose.Schema
, belongsTo = require('./belongsTo')
, hasMany = require('./hasMany')
, hasAndBelongsToMany = require('./hasAndBelongsToMany');
, habtmArrayFactory = require('./types/HasAndBelongsToManyArray')
, belongsTo
, hasAndBelongsToMany
, hasMany;

// register HasAndBelongsToMany Type
mongoose.Types.HasAndBelongsToManyArray = require('./types/HasAndBelongsToManyArray')(mongoose.Types.Array)

belongsTo = require('./belongsTo');
hasAndBelongsToMany = require('./hasAndBelongsToMany');
hasMany = require('./hasMany');

/* Syntactic sugar to create the relationships
*
* @param {String} model [name of the model in the DB]
* @param {Object} options [through, dependent]
* @return {Schema}
* @api public
*/
Schema.prototype.belongsTo = function (model, options) {
belongsTo(this, model, options);
};
Expand All @@ -22,8 +23,9 @@ module.exports = exports = function mongoRelations (mongoose) {
};

Schema.prototype.habtm = function (model, options) {
new hasAndBelongsToMany(this, model, options);
hasAndBelongsToMany(this, model, options);
};
Schema.prototype.hasAndBelongsToMany = Schema.prototype.habtm;

return mongoose;
};
11 changes: 11 additions & 0 deletions lib/types/HasAndBelongsToManyArray.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = exports = function (MongooseArray) {
var HasAndBelongsToManyArray;

function HasAndBelongsToManyArray ( ) {
MongooseArray.apply(this, arguments);
};
HasAndBelongsToManyArray.prototype = Object.create(MongooseArray.prototype);
HasAndBelongsToManyArray.prototype.build = function(){};

return HasAndBelongsToManyArray;
};
60 changes: 49 additions & 11 deletions specs/hasAndBelongsToMany.spec.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,54 @@
require('./spec_helper');

var mongoose = require('mongoose'),
should = require('should'),
TwitterUser = require('./support/twitterUserModel'),
Pet = require('./support/petModel')
Dog = require('./support/dogModel')
Fish = require('./support/fishModel')
TwitterPost = require('./support/twitterPostModel'),
Category = require('./support/categoryModel'),
Tweet = require('./support/tweetModel'),
Tag = require('./support/tagModel'),
BookSchema = new mongoose.Schema({});
var mongoose = require('mongoose')
, should = require('should')
, TwitterUser = require('./support/twitterUserModel')
, Pet = require('./support/petModel')
, Dog = require('./support/dogModel')
, Fish = require('./support/fishModel')
, TwitterPost = require('./support/twitterPostModel')
, Category = require('./support/categoryModel')
, Tweet = require('./support/tweetModel')
, Tag = require('./support/tagModel')
, BookSchema = new mongoose.Schema({});

describe('hasManyBelongsToMany without options', function() {
var paintingSchema, Painting, painting
, colorSchema, Color, color;

before(function(){
paintingSchema = new mongoose.Schema({ title: String });
paintingSchema.hasAndBelongsToMany('colors');
Painting = mongoose.model('Painting', paintingSchema);

colorSchema = new mongoose.Schema({ name: String });
colorSchema.habtm('paintings');
Color = mongoose.model('Color', colorSchema);
});

describe('#build', function(){
it.only('initializes a new document with the appropriate association', function(){
painting = new Painting({ title: 'Mona Lisa' });
color = painting.colors.build({ name: 'Black' });

should(color.paintings, 'paintings should contain painting.id').containEql(painting._id);
should(painting.colors, 'colors should contain color.id').containEql(color._id);
});
});

describe('#create', function(){
it('initializes a new document with the appropriate association', function(done){
painting = new Painting({ title: 'Mona Lisa' });
painting.colors.create({ name: 'Black' }, function(err, _, color){
should(color.paintings).containEql(painting._id);
should(color.isNew).be.false;
should(painting.colors).containEql(color._id);

done();
});
});
});
});

describe('hasManyBelongsToMany', function() {
describe('valid options', function() {
Expand Down
6 changes: 3 additions & 3 deletions specs/hasMany.spec.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
require('./spec_helper');

var mongoose = require('mongoose')
, async = require('async')
, should = require('should')
, uuid = require('node-uuid');
, async = require('async')
, should = require('should')
, uuid = require('node-uuid');

describe('hasMany without options', function(){
var userSchema, User, user, widgetSchema, Widget, widget;
Expand Down
45 changes: 0 additions & 45 deletions specs/relationship/hasAndBelongsToMany.spec.js

This file was deleted.

2 changes: 1 addition & 1 deletion specs/support/categoryModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ var CategorySchema = new mongoose.Schema({
CategorySchema.belongsTo('twitter_user', { through: 'editor' });

// should only delete the reference
CategorySchema.habtm('TwitterPost', { through: 'posts', dependent: 'delete' });
CategorySchema.habtm('posts', { modelName: 'TwitterPost', dependent: 'delete' });

CategorySchema.hasMany('pets');

Expand Down
2 changes: 1 addition & 1 deletion specs/support/petSchemaBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function PetSchemaBase() {

Schema.apply(this, arguments);

this.habtm('TwitterUser', { setParent: false });
this.habtm('twitter_users', { setParent: false });
this.belongsTo('category');
}
util.inherits(PetSchemaBase, Schema);
Expand Down
2 changes: 1 addition & 1 deletion specs/support/tweetModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ var mongoose = require('mongoose');
var tweetSchema = new mongoose.Schema({ title: String, body: String });

tweetSchema.belongsTo('author', { modelName: 'TwitterUser', required: true });
tweetSchema.habtm('Tag', { through: 'tags', setChild: false })
tweetSchema.habtm('tags', { setChild: false })

module.exports = mongoose.model('Tweet', tweetSchema);
3 changes: 1 addition & 2 deletions specs/support/twitterPostModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ var twitterPostSchema = new mongoose.Schema({

twitterPostSchema.belongsTo('author', { modelName: 'TwitterUser' });

// should not delete the reference
twitterPostSchema.habtm('Category');
twitterPostSchema.habtm('categories');

module.exports = mongoose.model('TwitterPost', twitterPostSchema);
2 changes: 1 addition & 1 deletion specs/support/twitterUserModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ twitterUserSchema.hasMany('categories');
twitterUserSchema.hasMany('tags', { dependent: 'nullify' });
twitterUserSchema.hasMany('tweets', { dependent: 'delete', inverse_of: 'author' });

twitterUserSchema.habtm('Pet', { setParent: false })
twitterUserSchema.habtm('pets', { setParent: false })

module.exports = mongoose.model('TwitterUser', twitterUserSchema);