关于构建包含使用 bookshelf.js 构建的模型的 Hapi.js 应用程序的建议
Suggestions on structuring Hapi.js app that includes Models built with bookshelf.js
我正在开发一个小型应用程序,我正在将 bookshelf.js
作为 ORM 进行集成。我正在努力的一件事情是构建我的应用程序,这样我就可以 require
其他模型,而不必在创建其他模型时注入它们。
例如:
中间件插件:
'use strict';
var Knex = require('knex');
exports.register = function(server, options, next) {
var knex = Knex({
client: 'mysql',
connection: server.settings.app.mysql
});
var bookshelf = require('bookshelf')(knex);
server.expose('bookshelf', bookshelf);
next();
};
exports.register.attributes = {
pkg: require('./package.json')
};
型号:
'use strict';
var Bluebird = require('bluebird');
var bcrypt = Bluebird.promisifyAll(require('bcrypt'));
var InvalidPasswordError = require('create-error')('InvalidPasswordError');
module.exports = function(bookshelf) {
var User = bookshelf.Model.extend({
tableName: 'user'
}, {
login: Bluebird.method(function(email, password) {
return new this({email: email.toLowerCase().trim()})
.fetch({require: true})
.tap(function(user) {
return bcrypt.compareAsync(password, user.get('encrypted_password'))
.then(function (matches) {
if (!matches) throw new InvalidPasswordError();
})
})
})
});
return User;
};
我在路由中的调用方式:
var bookshelf = server.plugins['bookshelf'].bookshelf;
var User = require('../models/user')(bookshelf);
server.route([
{
method: 'POST',
path: '/auth/login',
config: {
auth: false,
payload: { allow: 'application/json' },
handler: function(request, reply) {
var email = request.payload.email;
var pwd = request.payload.password;
User.login(email, pwd).then(function(user) {
reply(user.pick('api_token'));
}).catch(User.NotFoundError, function() {
reply(Boom.badRequest('Invalid Email', 400));
}).catch(function(err) {
reply(Boom.badRequest('Invalid Password', 400));
});
},
validate: {
payload: Joi.object().keys({
email: Joi.string().email().required(),
password: Joi.string().required()
})
}
}
}
]);
我感到困惑的部分是设置将存在于我的 User
模型中的关联。例如,用户通过联接 table 拥有多个项目。但是,如果我想设置该关联,我必须首先将我的 bookshelf
对象传递给每个模型(Project 和 UserProject),然后将关联模型 (UserProject) 传递给每个 User 和 Project。
这看起来不太干净。它可能会很快变得凌乱。还有其他人有 and/or 使用 ORM 构建 Hapi.js 或 Node 应用程序的经验吗?
看看 registry
plugin
.正如插件文档所述,您必须确保某处需要您的模型,以便调用 bookshelf.model
。
// db/index.js
var _ = require('lodash');
var Promise = require('bluebird');
var models = require('require-dir')('./models');
var bookshelf = require('bookshelf')(knexClient);
bookshelf.plugin('registry');
for (var model in models) {
models[model] = models[model](_, Promise, bookshelf);
}
module.exports = models;
// db/models/User.js
module.exports = function (_, Promise, bookshelf) {
var User = bookshelf.model('User', {
tableName: 'users',
projects: function () {
return this.hasMany('Project');
}
// more proto props or relations
},
{
// constructor props
});
return User;
};
// db/models/Project.js
module.exports = function (_, Promise, bookshelf) {
var Project = bookshelf.model('Project', {
tableName: 'projects'
},
{
});
return Project;
};
你可以在你的路线中要求模型,关系将全部挂钩。 projects
集合可以通过User
模型查询。下面我使用 fetchOne。
// route.js
var User = require('../db').User;
module.exports = function (app) {
app.get('/projects/:projectId', function (req, res) {
return User
.forge({ id: req.auth.userId })
.projects()
.query({where: { id: req.params.projectId } })
.fetchOne()
.then(function (project) {
res.send(project);
});
});
};
我正在开发一个小型应用程序,我正在将 bookshelf.js
作为 ORM 进行集成。我正在努力的一件事情是构建我的应用程序,这样我就可以 require
其他模型,而不必在创建其他模型时注入它们。
例如:
中间件插件:
'use strict';
var Knex = require('knex');
exports.register = function(server, options, next) {
var knex = Knex({
client: 'mysql',
connection: server.settings.app.mysql
});
var bookshelf = require('bookshelf')(knex);
server.expose('bookshelf', bookshelf);
next();
};
exports.register.attributes = {
pkg: require('./package.json')
};
型号:
'use strict';
var Bluebird = require('bluebird');
var bcrypt = Bluebird.promisifyAll(require('bcrypt'));
var InvalidPasswordError = require('create-error')('InvalidPasswordError');
module.exports = function(bookshelf) {
var User = bookshelf.Model.extend({
tableName: 'user'
}, {
login: Bluebird.method(function(email, password) {
return new this({email: email.toLowerCase().trim()})
.fetch({require: true})
.tap(function(user) {
return bcrypt.compareAsync(password, user.get('encrypted_password'))
.then(function (matches) {
if (!matches) throw new InvalidPasswordError();
})
})
})
});
return User;
};
我在路由中的调用方式:
var bookshelf = server.plugins['bookshelf'].bookshelf;
var User = require('../models/user')(bookshelf);
server.route([
{
method: 'POST',
path: '/auth/login',
config: {
auth: false,
payload: { allow: 'application/json' },
handler: function(request, reply) {
var email = request.payload.email;
var pwd = request.payload.password;
User.login(email, pwd).then(function(user) {
reply(user.pick('api_token'));
}).catch(User.NotFoundError, function() {
reply(Boom.badRequest('Invalid Email', 400));
}).catch(function(err) {
reply(Boom.badRequest('Invalid Password', 400));
});
},
validate: {
payload: Joi.object().keys({
email: Joi.string().email().required(),
password: Joi.string().required()
})
}
}
}
]);
我感到困惑的部分是设置将存在于我的 User
模型中的关联。例如,用户通过联接 table 拥有多个项目。但是,如果我想设置该关联,我必须首先将我的 bookshelf
对象传递给每个模型(Project 和 UserProject),然后将关联模型 (UserProject) 传递给每个 User 和 Project。
这看起来不太干净。它可能会很快变得凌乱。还有其他人有 and/or 使用 ORM 构建 Hapi.js 或 Node 应用程序的经验吗?
看看 registry
plugin
.正如插件文档所述,您必须确保某处需要您的模型,以便调用 bookshelf.model
。
// db/index.js
var _ = require('lodash');
var Promise = require('bluebird');
var models = require('require-dir')('./models');
var bookshelf = require('bookshelf')(knexClient);
bookshelf.plugin('registry');
for (var model in models) {
models[model] = models[model](_, Promise, bookshelf);
}
module.exports = models;
// db/models/User.js
module.exports = function (_, Promise, bookshelf) {
var User = bookshelf.model('User', {
tableName: 'users',
projects: function () {
return this.hasMany('Project');
}
// more proto props or relations
},
{
// constructor props
});
return User;
};
// db/models/Project.js
module.exports = function (_, Promise, bookshelf) {
var Project = bookshelf.model('Project', {
tableName: 'projects'
},
{
});
return Project;
};
你可以在你的路线中要求模型,关系将全部挂钩。 projects
集合可以通过User
模型查询。下面我使用 fetchOne。
// route.js
var User = require('../db').User;
module.exports = function (app) {
app.get('/projects/:projectId', function (req, res) {
return User
.forge({ id: req.auth.userId })
.projects()
.query({where: { id: req.params.projectId } })
.fetchOne()
.then(function (project) {
res.send(project);
});
});
};