#リポジトリ
https://github.com/kbc18a11/oreoreExpress
ライブラリ本体はoreoreExpress/database/AbstractModel.js
です。
#解説用の構成や注意点
- FW:Express
- ディレクトリ構成:WebStormの新規Expressプロジェクトの状態に
プロジェクト名/database
とプロジェクト名/model
というディレクトリを生成 - 本記事はチーム開発のメンバーのマニュアルとしても書いていますので、ライブラリには直接関係ないことも書いています。
今回利用しているtestsテーブルは以下の構成になっています
id | text | created_at | updated_at |
---|
#使い方
リポジトリのものを利用するのであれば、以下のコマンドを実行してください。
npm install mysql2
ライブラリだけを使用するのであれば、mysql2
とdate-utlis
をインストールします
npm install mysql2
npm install date-utlis
そして以下のとおり、mysql2の設定ファイルを作ります。
const mysql = require('mysql2');
//MySQLの接続設定
const connection = mysql.createConnection({
host: 'localhost',
user: '',
password: '',
database: ''
}).promise();
module.exports = connection;
下記の通り、作りたいモデルクラスに設定します。
また以下のメソッドをオーバーライド、オーバーロードします。
abstractTABLE_NAME
abstractVALIDATIONRULES
update
メソッドabstractTABLE_NAME
は、連携しているテーブル名のです。
メソッドabstractVALIDATIONRULES
は、バリエーションルールを記述する所です。
バリエーションのルールはvalidatorjsのものになります。
https://www.npmjs.com/package/validatorjs
const AbstractModel = require('./AbstractModel');
const connection = require('../database/mysqlConnection');
require('date-utils');
class Tests extends AbstractModel {
constructor() {
super();
}
/**
* テーブル名
* @override
* @returns {string}
*/
static get abstractTABLE_NAME() {
return 'tests';
}
/**
* バリデーションルール
* @override
* @return {Object}
*/
static get abstractVALIDATIONRULES() {
return {
get:{
rule: {
id: 'required|integer'
},
errorMessage: {
required: '必須項目です。',
integer: '数値で入力してください'
}
},
//POSTリクエスト用
post: {
rule: {
text: 'required'
},
errorMessage: {
required: '必須項目です。',
}
},
//PUTリクエスト用
put: {
rule: {
id: 'required|integer',
text: 'required'
},
errorMessage: {
required: '必須項目です。',
integer: '数値で入力してください'
}
},
//DELETEリクエスト用
delete: {
rule: {
id: 'required|integer'
},
errorMessage: {
required: '必須項目です。',
integer: '数値で入力してください'
}
}
};
}
/**
* UPDATE文の準備を行って、親クラスのupdate()に実行をさせる
* @param {Object} insertParam
*/
static async update(insertParam) {
//UPDATE文
const sql = `UPDATE ${this.abstractTABLE_NAME} SET text = ?,updated_at = ? WHERE id = ?`;
//create_at用の日付時間取得
insertParam.updated_at = new Date().toFormat('YYYY-MM-DD HH:MI:SS');
//SQLの実行
await super.update(insertParam, sql);
}
}
module.exports = Tests;
#機能
基本的にライブラリの機能を使う場合は、Expressのルーティングファイルの無名関数にasync
を付与します。
router.get('/tests', async (req, res, next) => {
そして、ルーティングファイルで以下のライブラリを取り組みます。
const express = require('express');
const router = express.Router();
const validator = require('validatorjs');
const Tests = require('../model/Tests');
ライブラリでデータベースを操作するメソッドは、Promiseオブジェクトがかかわっているため、呼び出しの際には、await
を付与します。
//レコードをすべて取得
await Test.all()
//引数idのカラム取得
await Test.find(id)
//引数idの存在確認を行う
await Test.existId(id)
//引数paramの値で新規登録を行う
await Test.insert(param)
//引数paramの値で更新を行う
await Test.update(param)
//引数idのレコードを削除する
await Test.delete(id)
##all() レコードをすべて取得
/**
* @GET
* testsのレコードをすべて取得
*/
router.get('/tests', async (req, res, next) => {
try {
//レコードをすべて取得
const allRows = await Tests.all();
//レコードを返す
return res.send(allRows);
} catch (error) {
//レコードの取得失敗時
console.log(error);
res.status(500);
return res.send({'error': 'サーバー側でエラーが発生しました'});
}
});
http://localhost:3000/tests にGET
でアクセスします。
[
{
"id": 1,
"text": "これはテストです",
"created_at": "2020-06-18T16:50:45.000Z",
"updated_at": null
},
{
"id": 2,
"text": "これはテストです",
"created_at": "2020-06-18T16:50:50.000Z",
"updated_at": null
},
{
"id": 3,
"text": "これはテストです",
"created_at": "2020-06-18T16:50:51.000Z",
"updated_at": null
}
]
##find(id) 引数idのカラム取得
/**
* @GET
* 指定されたidのカラムを取得
*/
router.get('/tests/:id', async (req, res, next) => {
//バリデーションの検証を受ける値
const verificationValue = {
id: req.params.id
}
//バリデーションの結果にエラーがあるかのチェック
const validation = new validator(
verificationValue,
Tests.abstractVALIDATIONRULES.get.rule,
Tests.abstractVALIDATIONRULES.get.errorMessage
);
if (validation.fails()) {
//エラーを422で返す
return res.status(422).send({errors: validation.errors.all()});
}
try {
//レコードを取得
const row = await Tests.find(verificationValue.id);
//レコードを返す
return res.send(row);
} catch (error) {
//レコードの取得失敗時
console.log(error);
res.status(500);
return res.send({'error': 'サーバー側でエラーが発生しました'});
}
})
http://localhost:3000/(testのidを指定) にGET
でアクセスします。
[
{
"id": 1,
"text": "これはテストです",
"created_at": "2020-06-18T16:50:45.000Z",
"updated_at": null
}
]
また、URIのidを指定する所が以下のとおり数値以外の場合は、エラーメッセージを返します。
http://localhost:3000/aaaa77
{
"errors": {
"id": [
"数値で入力してください"
]
}
}
insert() 引数paramの値で新規登録を行う
/**
* @POST
* testsに新しいレコードを挿入
*/
router.post('/test', async (req, res, next) => {
//バリデーションの検証を受ける値
const verificationValue = {
text: req.query.text
}
//バリデーションの結果にエラーがあるかのチェック
const validation = new validator(
verificationValue,
Tests.abstractVALIDATIONRULES.post.rule,
Tests.abstractVALIDATIONRULES.post.errorMessage
);
if (validation.fails()) {
//エラーを422で返す
return res.status(422).send({errors: validation.errors.all()});
}
try {
//レコードの挿入開始
await Tests.insert({text: req.query.text});
return res.send({'insertResult': true});
} catch (error) {
//レコードの挿入失敗時
console.log(error);
return res.status(500).send({'insertResult': false});
}
});
http://localhost:3000/test?text=テストやりたい にPOST
でアクセスします。
[
{
"id": 1,
"text": "これはテストです",
"created_at": "2020-06-18T16:50:45.000Z",
"updated_at": null
}
]
リクエストのボディにtextがない場合は、エラーメッセージを返します。
{
"errors": {
"text": [
"必須項目です。"
]
}
}
update(param) 引数paramの値で更新を行う existId(id) 引数idの存在確認を行う
/**
* @PUT
* レコードの更新
*/
router.put('/test/:id', async (req, res, next) => {
//バリデーションの検証を受ける値
const verificationValue = {
id: req.params.id,
text: req.query.text
}
//バリデーションの結果にエラーがあるかのチェック
const validation = new validator(
verificationValue,
Tests.abstractVALIDATIONRULES.put.rule,
Tests.abstractVALIDATIONRULES.put.errorMessage
);
if (validation.fails()) {
//エラーを422で返す
return res.status(422).send({errors: validation.errors.all()});
}
//idは存在しないか?
if (!await Tests.existId(verificationValue.id)) {
//エラーを422で返す
return res.status(422).send({
errors: {
id: ['idが存在しません']
}
});
}
try {
//レコードの更新開始
await Tests.update(verificationValue);
return res.send({'updateResult': true});
} catch (error) {
//レコードの更新失敗時
console.log(error);
return res.status(500).send({'updateResult': false});
}
});
http://localhost:3000/test?text=テストやりたい にPUT
でアクセスします。
{
"updateResult": true
}
URIのidを指定する所が以下のとおり数値以外やリクエストのボディにtextがない場合は、エラーメッセージを返します。
http://localhost:3000/test/aaa
{
"errors": {
"id": [
"数値で入力してください"
],
"text": [
"必須項目です。"
]
}
}
そして、find(id)
の引数のidがレコードに存在しない場合、このようなエラーを返します
{
"errors": {
"id": [
"idが存在しません"
]
}
}
delete(id) 引数idのレコードを削除する
/**
* @DELETE
* レコードの削除
*/
router.delete('/test/:id', async (req, res, next) => {
//バリデーションの検証を受ける値
const verificationValue = {
id: req.params.id,
}
//バリデーションの結果にエラーがあるかのチェック
const validation = new validator(
verificationValue,
Tests.abstractVALIDATIONRULES.delete.rule,
Tests.abstractVALIDATIONRULES.delete.errorMessage
);
if (validation.fails()) {
//エラーを422で返す
return res.status(422).send({errors: validation.errors.all()});
}
//idは存在しないか?
if (!await Tests.existId(verificationValue.id)) {
//エラーを422で返す
return res.status(422).send({
errors: {
id: ['idが存在しません']
}
});
}
try {
//レコードの削除開始
await Tests.delete(verificationValue.id);
return res.send({'deleteResult': true});
} catch (error) {
//レコードの削除失敗時
console.log(error);
return res.status(500).send({'deleteResult': false});
}
})
http://localhost:3000/(testのidを指定) にDELETE
でアクセスします。
[
{
"id": 1,
"text": "これはテストです",
"created_at": "2020-06-18T16:50:45.000Z",
"updated_at": null
}
]
URIのidを指定する所が以下のとおり数値以外の場合は、エラーメッセージを返します。
http://localhost:3000/aaaa77
{
"errors": {
"id": [
"数値で入力してください"
]
}
}
そして、find(id)
の引数のidがレコードに存在しない場合、このようなエラーを返します
{
"errors": {
"id": [
"idが存在しません"
]
}
}