Permalink
Browse files

added; model.create returns a promise

callback is now optional.

closes #1340
  • Loading branch information...
aheckmann committed Apr 22, 2013
1 parent 0a29071 commit 2ef5f237e054fc4846143530410e353ef7a7456e
Showing with 136 additions and 58 deletions.
  1. +36 −16 lib/model.js
  2. +100 −0 test/model.create.test.js
  3. +0 −42 test/model.test.js
View
@@ -1326,51 +1326,71 @@ Model.findByIdAndRemove = function (id, options, callback) {
*
* ####Example:
*
* // pass individual docs
* Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {
* if (err) // ...
* });
*
* // pass an array
* var array = [{ type: 'jelly bean' }, { type: 'snickers' }];
* Candy.create(array, function (err, jellybean, snickers) {
* if (err) // ...
* });
*
* // callback is optional; use the returned promise if you like:
* var promise = Candy.create({ type: 'jawbreaker' });
* promise.then(function (jawbreaker) {
* // ...
* })
*
* @param {Array|Object...} doc
* @param {Function} fn callback
* @param {Function} [fn] callback
* @return {Promise}
* @api public
*/
Model.create = function create (doc, fn) {
if (1 === arguments.length) {
return 'function' === typeof doc && doc(null);
}
var self = this
, docs = [null]
, promise
, count
var promise = new Promise
, args
if (Array.isArray(doc)) {
args = doc;
if ('function' == typeof fn) {
promise.onResolve(fn);
}
} else {
args = utils.args(arguments, 0, arguments.length - 1);
fn = arguments[arguments.length - 1];
var last = arguments[arguments.length - 1];
if ('function' == typeof last) {
promise.onResolve(last);
args = utils.args(arguments, 0, arguments.length - 1);
} else {
args = utils.args(arguments);
}
}
if (0 === args.length) return fn(null);
var count = args.length;
promise = new Promise(fn);
count = args.length;
if (0 === count) {
promise.complete();
return promise;
}
var self = this;
var docs = [];
args.forEach(function (arg, i) {
var doc = new self(arg);
docs[i+1] = doc;
docs[i] = doc;
doc.save(function (err) {
if (err) return promise.error(err);
--count || fn.apply(null, docs);
--count || promise.complete.apply(promise, docs);
});
});
return promise;
};
/**
View
@@ -0,0 +1,100 @@
/**
* Test dependencies.
*/
var start = require('./common')
, assert = require('assert')
, mongoose = start.mongoose
, random = require('../lib/utils').random
, Schema = mongoose.Schema
, DocumentObjectId = mongoose.Types.ObjectId
/**
* Setup
*/
var schema = Schema({
title: String
})
describe('model', function(){
describe('create()', function(){
var db;
var B;
before(function(){
db = start();
B = db.model('model-create', schema, 'model-create-'+random());
})
after(function(done){
db.close(done);
})
it('accepts an array', function(done){
B.create([{ title: 'hi'}, { title: 'bye'}], function (err, post1, post2) {
assert.ifError(err);
assert.ok(post1.get('_id') instanceof DocumentObjectId);
assert.equal(post1.title,'hi');
assert.ok(post2.get('_id') instanceof DocumentObjectId);
assert.equal(post2.title,'bye');
done();
});
});
it('fires callback when passed 0 docs', function(done){
B.create(function (err, a) {
assert.ifError(err);
assert.ok(!a);
done();
});
});
it('fires callback when empty array passed', function(done){
B.create([], function (err, a) {
assert.ifError(err);
assert.ok(!a);
done();
});
});
it('returns a promise', function(done){
var p = B.create({ title: 'returns promise' }, function(){
assert.ok(p instanceof mongoose.Promise);
done();
});
})
describe('callback is optional', function(){
it('with one doc', function(done){
var p = B.create({ title: 'optional callback' });
p.then(function (doc) {
assert.equal('optional callback', doc.title);
done();
}, done).end();
})
it('with more than one doc', function(done){
var p = B.create({ title: 'optional callback 2' }, { title: 'orient expressions' });
p.then(function (doc1, doc2) {
assert.equal('optional callback 2', doc1.title);
assert.equal('orient expressions', doc2.title);
done();
}, done).end();
})
it('with array of docs', function(done){
var p = B.create([{ title: 'optional callback3' }, { title: '3' }]);
p.then(function (doc1, doc2) {
assert.equal('optional callback3', doc1.title);
assert.equal('3', doc2.title);
done();
}, done).end();
})
})
});
})
View
@@ -4263,48 +4263,6 @@ describe('Model', function(){
})
});
describe('create()', function(){
it('accepts an array', function(done){
var db = start()
, BlogPost = db.model('BlogPost', collection);
BlogPost.create([{ title: 'hi'}, { title: 'bye'}], function (err, post1, post2) {
db.close();
assert.strictEqual(err, null);
assert.ok(post1.get('_id') instanceof DocumentObjectId);
assert.ok(post2.get('_id') instanceof DocumentObjectId);
assert.equal(post1.title,'hi');
assert.equal(post2.title,'bye');
done();
});
});
it('fires callback when passed 0 docs', function(done){
var db = start()
, BlogPost = db.model('BlogPost', collection);
BlogPost.create(function (err, a) {
db.close();
assert.strictEqual(err, null);
assert.ok(!a);
done();
});
});
it('fires callback when empty array passed', function(done){
var db = start()
, BlogPost = db.model('BlogPost', collection);
BlogPost.create([], function (err, a) {
db.close();
assert.strictEqual(err, null);
assert.ok(!a);
done();
});
});
});
describe('non-schema adhoc property assignments', function(){
it('are not saved', function(done){
var db = start()

0 comments on commit 2ef5f23

Please sign in to comment.