Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Batch create, misc #250

Merged
merged 7 commits into from Mar 31, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -9,3 +9,4 @@ benchmark.js
analyse.r analyse.r
docs/html docs/html
docs/man docs/man
npm-debug.log
1 change: 1 addition & 0 deletions .npmignore
Expand Up @@ -8,3 +8,4 @@ v8.log
benchmark.js benchmark.js
analyse.r analyse.r
docs/html docs/html
npm-debug.log
9 changes: 9 additions & 0 deletions docs/model.md
Expand Up @@ -22,6 +22,15 @@ instance.
console.log(user instanceof User); 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]]); ### Model.prototype.save([options[, callback]]);


Save instance to database, options is an object {validate: true, throws: false}, Save instance to database, options is an object {validate: true, throws: false},
Expand Down
2 changes: 1 addition & 1 deletion lib/adapters/memory.js
Expand Up @@ -181,7 +181,7 @@ Memory.prototype.count = function count(model, callback, where) {


Memory.prototype.updateAttributes = function updateAttributes(model, id, data, cb) { Memory.prototype.updateAttributes = function updateAttributes(model, id, data, cb) {
data.id = id; data.id = id;
var base = this.cache[model][id]; var base = JSON.parse(this.cache[model][id]);
this.save(model, merge(base, data), cb); this.save(model, merge(base, data), cb);
}; };


Expand Down
36 changes: 33 additions & 3 deletions lib/model.js
Expand Up @@ -160,7 +160,8 @@ AbstractClass.prototype.whatTypeName = function (propName) {
AbstractClass.create = function (data, callback) { AbstractClass.create = function (data, callback) {
if (stillConnecting(this.schema, this, arguments)) return; if (stillConnecting(this.schema, this, arguments)) return;


var modelName = this.modelName; var Model = this;
var modelName = Model.modelName;


if (typeof data === 'function') { if (typeof data === 'function') {
callback = data; callback = data;
Expand All @@ -171,12 +172,39 @@ AbstractClass.create = function (data, callback) {
callback = function () {}; 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; var obj;
// if we come from save // if we come from save
if (data instanceof this && !data.id) { if (data instanceof Model && !data.id) {
obj = data; obj = data;
} else { } else {
obj = new this(data); obj = new Model(data);
} }
data = obj.toObject(true); data = obj.toObject(true);


Expand Down Expand Up @@ -215,6 +243,8 @@ AbstractClass.create = function (data, callback) {
}, data); }, data);
}, data); }, data);
} }

return obj;
}; };


function stillConnecting(schema, obj, args) { function stillConnecting(schema, obj, args) {
Expand Down
13 changes: 10 additions & 3 deletions lib/validations.js
Expand Up @@ -374,15 +374,22 @@ Validatable.prototype.isValid = function (callback, data) {
}); });


if (!async) { if (!async) {
validationsDone.call(inst, callback); validationsDone.call(inst, function() {
if (valid) cleanErrors(inst);
if (callback) {
callback(valid);
}
});
} }


function done(fail) { function done(fail) {
asyncFail = asyncFail || fail; asyncFail = asyncFail || fail;
if (--wait === 0 && callback) { if (--wait === 0) {
validationsDone.call(inst, function () { validationsDone.call(inst, function () {
if (valid && !asyncFail) cleanErrors(inst); if (valid && !asyncFail) cleanErrors(inst);
callback(valid && !asyncFail); if (callback) {
callback(valid && !asyncFail);
}
}); });
} }
} }
Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,7 +1,7 @@
{ {
"name": "jugglingdb", "name": "jugglingdb",
"description": "ORM for every database: redis, mysql, neo4j, mongodb, couchdb, postgres, sqlite", "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>", "author": "Anatoliy Chakkaev <rpm1602@gmail.com>",
"contributors": [ "contributors": [
{ {
Expand Down
60 changes: 59 additions & 1 deletion test/manipulation.test.js
Expand Up @@ -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) { it('should work when called without callback', function(done) {
Person.afterCreate = function(next) { Person.afterCreate = function(next) {
this.should.be.an.instanceOf(Person); this.should.be.an.instanceOf(Person);
Expand Down Expand Up @@ -69,10 +79,35 @@ describe('manipulation', function() {
should.exist(this.id); should.exist(this.id);
Person.afterCreate = null; Person.afterCreate = null;
next(); next();
setTimeout(done, 10); setTimeout(done, 30);
}; };
Person.create(); 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() { describe('save', function() {
Expand Down Expand Up @@ -138,6 +173,29 @@ describe('manipulation', function() {
}).should.throw('Validation error'); }).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() { describe('destroy', function() {
Expand Down