Merge pull request #250 from anatoliychakkaev/master

Batch create, misc
This commit is contained in:
Anatoliy Chakkaev 2013-03-31 03:08:18 -07:00
commit f8f72cc05e
8 changed files with 115 additions and 9 deletions

1
.gitignore vendored
View File

@ -9,3 +9,4 @@ benchmark.js
analyse.r
docs/html
docs/man
npm-debug.log

View File

@ -8,3 +8,4 @@ v8.log
benchmark.js
analyse.r
docs/html
npm-debug.log

View File

@ -22,6 +22,15 @@ instance.
console.log(user instanceof User);
});
When called with array of objects as first argument `Model.create` creates bunch
of records. Both `err` and `model instance` arguments passed to callback will be
arrays then. When no errors happened `err` argument will be null.
The value returned from `Model.create` depends on second argument too. In case
of Array it will return an array of instances, otherwise single instance. But be
away, this instance(s) aren't save to database yet and you have to wait until
callback called to be able to do id-sensitive stuff.
### Model.prototype.save([options[, callback]]);
Save instance to database, options is an object {validate: true, throws: false},

View File

@ -181,7 +181,7 @@ Memory.prototype.count = function count(model, callback, where) {
Memory.prototype.updateAttributes = function updateAttributes(model, id, data, cb) {
data.id = id;
var base = this.cache[model][id];
var base = JSON.parse(this.cache[model][id]);
this.save(model, merge(base, data), cb);
};

View File

@ -160,7 +160,8 @@ AbstractClass.prototype.whatTypeName = function (propName) {
AbstractClass.create = function (data, callback) {
if (stillConnecting(this.schema, this, arguments)) return;
var modelName = this.modelName;
var Model = this;
var modelName = Model.modelName;
if (typeof data === 'function') {
callback = data;
@ -171,12 +172,39 @@ AbstractClass.create = function (data, callback) {
callback = function () {};
}
if (data instanceof Array) {
var instances = [];
var errors = new Array(data.length);
var gotError = false;
var wait = data.length;
if (wait === 0) callback(null, []);
var instances = data.map(function(d, i) {
return Model.create(d, function(err, inst) {
// console.log('got', i, err, inst, inst.errors);
if (err) {
errors[i] = err;
gotError = true;
}
modelCreated();
});
});
return instances;
function modelCreated() {
if (--wait === 0) {
callback(gotError ? errors : null, instances);
}
}
}
var obj;
// if we come from save
if (data instanceof this && !data.id) {
if (data instanceof Model && !data.id) {
obj = data;
} else {
obj = new this(data);
obj = new Model(data);
}
data = obj.toObject(true);
@ -215,6 +243,8 @@ AbstractClass.create = function (data, callback) {
}, data);
}, data);
}
return obj;
};
function stillConnecting(schema, obj, args) {

View File

@ -374,15 +374,22 @@ Validatable.prototype.isValid = function (callback, data) {
});
if (!async) {
validationsDone.call(inst, callback);
validationsDone.call(inst, function() {
if (valid) cleanErrors(inst);
if (callback) {
callback(valid);
}
});
}
function done(fail) {
asyncFail = asyncFail || fail;
if (--wait === 0 && callback) {
if (--wait === 0) {
validationsDone.call(inst, function () {
if (valid && !asyncFail) cleanErrors(inst);
callback(valid && !asyncFail);
if (callback) {
callback(valid && !asyncFail);
}
});
}
}

View File

@ -1,7 +1,7 @@
{
"name": "jugglingdb",
"description": "ORM for every database: redis, mysql, neo4j, mongodb, couchdb, postgres, sqlite",
"version": "0.2.0-25",
"version": "0.2.0-27",
"author": "Anatoliy Chakkaev <rpm1602@gmail.com>",
"contributors": [
{

View File

@ -37,6 +37,16 @@ describe('manipulation', function() {
});
});
it('should return instance of object', function(done) {
var person = Person.create(function(err, p) {
p.id.should.eql(person.id);
done();
});
should.exist(person);
person.should.be.an.instanceOf(Person);
should.not.exist(person.id);
});
it('should work when called without callback', function(done) {
Person.afterCreate = function(next) {
this.should.be.an.instanceOf(Person);
@ -69,10 +79,35 @@ describe('manipulation', function() {
should.exist(this.id);
Person.afterCreate = null;
next();
setTimeout(done, 10);
setTimeout(done, 30);
};
Person.create();
});
it('should create batch of objects', function(done) {
var batch = [{name: 'Shaltay'}, {name: 'Boltay'}, {}];
Person.create(batch, function(e, ps) {
should.not.exist(e);
should.exist(ps);
ps.should.be.instanceOf(Array);
ps.should.have.lengthOf(batch.length);
Person.validatesPresenceOf('name');
Person.create(batch, function(errors, persons) {
delete Person._validations;
should.exist(errors);
errors.should.have.lengthOf(batch.length);
should.not.exist(errors[0]);
should.not.exist(errors[1]);
should.exist(errors[2]);
should.exist(persons);
persons.should.have.lengthOf(batch.length);
persons[0].errors.should.be.false;
done();
}).should.be.instanceOf(Array);
}).should.have.lengthOf(3);
});
});
describe('save', function() {
@ -138,6 +173,29 @@ describe('manipulation', function() {
}).should.throw('Validation error');
});
});
});
describe('updateAttributes', function() {
var person;
before(function(done) {
Person.destroyAll(function() {
person = Person.create(done);
});
});
it('should update one attribute', function(done) {
person.updateAttribute('name', 'Paul Graham', function(err, p) {
should.not.exist(err);
Person.all(function(e, ps) {
should.not.exist(err);
ps.should.have.lengthOf(1);
ps.pop().name.should.equal('Paul Graham');
done();
});
});
});
});
describe('destroy', function() {