Permalink
Browse files

feat: yukari insert

  • Loading branch information...
XadillaX committed Sep 21, 2016
1 parent b230cea commit 04636269fdb9c049868a6ff48d6166b46b439221
Showing with 105 additions and 4 deletions.
  1. +97 −0 lib/yukari.js
  2. +2 −2 package.json
  3. +6 −2 test/adapters/mysql.js
@@ -7,6 +7,9 @@
"use strict";

const _ = require("lodash");
const async = require("async");

const _emptyCallback = function() {};

class Yukari {
constructor(model, source) {
@@ -107,6 +110,100 @@ class Yukari {

return -1;
}

validateOne(name, value, callback) {
const self = this;
const fieldIdx = this.fieldAt(name);
if(-1 === fieldIdx) {
return callback(new Error(`No such field ${name}`));
}

const field = this.$schema[fieldIdx];

if(null === value) {
return callback(field.allowNull ? undefined : new Error(`Field ${name} can't be null.`));
}

if(!field.validators.length) {
return callback();
}

let err;
let i = 0;
async.whilst(
() => (!err && i < field.validators.length),
function(callback) {
const validator = field.validators[i++];
if(validator.length <= 1) {
const result = (validator.bind(self.$model))(value);
if(typeof result === "string" && result.length) {
err = new Error(result);
return callback(err);
}
} else {
return (validator.bind(self.$model))(value, function(_err) {
if(_err) {
err = _err;
}

return callback(err);
});
}
callback();
},
function() {
return callback(err);
});
}

validateAll(callback) {
const self = this;
async.eachLimit(Object.keys(this), 10, function(key, callback) {
if(!self.hasOwnProperty(key)) return callback();
if(key && (key[0] === "$" || typeof self[key] === "function" || self.fieldAt(key) === -1)) {
return callback();
}

self.validateOne(key, self[key], function(err) {
return callback(err);
});
}, function(err) {
return callback(err);
});
}

insert(callback) {
if(callback === undefined) {
callback = _emptyCallback;
}

if(this.$source !== "new") {
return callback(new Error("You must call this function via a new Yukari object."));
}

const self = this;

async.waterfall([
self.validateAll.bind(self),
self.$adapter.insert.bind(self.$adapter, self.$model, self)
], function(err, row, extra) {
if(err) return callback(err, null, extra);

// clone new row's data to self
for(const key in row) {
if(!row.hasOwnProperty(key)) continue;
if(key && key[0] === "$" && key !== "$origData") {
continue;
}

if(typeof row[key] === "function") continue;

self[key] = _.cloneDeep(row[key]);
}

return callback(undefined, self, extra);
});
}
}

module.exports = Yukari;
@@ -28,7 +28,7 @@
"mocha": "3.0.1",
"mockjs": "^1.0.1-beta3",
"mysql": "^2.11.1",
"mysql2": "^1.0.0-rc.9",
"mysql2": "^1.1.0",
"should": "10.0.0",
"sync-runner": "^0.1.5",
"toshihiko-memcached": "^1.0.1",
@@ -73,4 +73,4 @@
"pre-push": "npm test"
}
}
}
}
@@ -145,7 +145,9 @@ describe("🐣 adapters/mysql", function() {
[ "mysql", "mysql2" ].forEach(name => {
describe(name, function() {
before(function(done) {
const adapter = new MySQLAdapter({}, correctOptions);
const options = cu.extendDeep({}, correctOptions);
options.package = name;
const adapter = new MySQLAdapter({}, options);
adapter.execute("DROP TABLE IF EXISTS `test1`;", function(err) {
should.ifError(err);
adapter.execute("DROP TABLE IF EXISTS `test2`;", function(err) {
@@ -217,7 +219,9 @@ describe("🐣 adapters/mysql", function() {
key3: { foo: "bar" },
key4: null,
key5: now,
key6: { dec: 168 }
key6: { dec: 168 },
$123: 1,
ok: function() {}
}, function(err, _row) {
should.ifError(err);
const row = cu.extendDeep({}, _row);

0 comments on commit 0463626

Please sign in to comment.