※node.js超入門ノートの続きになります。
モデルの実装
以下のコマンドを実行します。
npx sequelize-cli model:generate --name Board --attributes userId:integer, message:string
アソシエーションの設定
作成したファイルを修正します。
models/board.js
// 従モデル
'use strict';
module.exports = (sequelize, DataTypes) => {
const Board = sequelize.define('Board', {
userId: {
type: DataTypes.INTEGER,
validate: {
notEmpty: {
msg: "利用者は必須です。"
}
}
},
message: {
type: DataTypes.STRING,
validate: {
notEmpty: {
msg: "メッセージは必須です。"
}
}
}
}, {});
Board.associate = function(models) {
Board.belongsTo(models.User); // 従モデル
};
return Board;
};
以下も修正します。
models/user.js
User.associate = function(models) {
User.hasMany(models.Board); // 主モデル
};
以下のコマンドでマイグレーションを行います。
npx sequelize-cli db:migrate
ログイン処理
ログイン処理を追記します。
routes/users.js
router.get('/login', (req, res, next) => {
var data = {
title:'Users/Login',
content: '名前とパスワードを入力してください。'
}
res.render('users/login', data);
});
router.post('/login', (req, res, next) => {
db.User.findOne({
where:{
name: req.body.name,
pass:req.body.pass,
}
}).then(usr => {
if (usr != null) {
req.session.login = usr;
let back = req.session.back;
if (back == null){
back = '/';
}
res.redirect(back);
} else {
var data = {
title: 'Users/Login',
content:'名前かパスワードに問題があります。再度入力して下さい。'
}
res.render('users/login', data);
}
})
});
以下のファイルを作成します。
routes/boards.js
const express = require('express');
const router = express.Router();
const db = require('../models/index');
const { Op } = require("sequelize");
const { route } = require('./users');
const pnum = 10;
// ログインのチェック
function check(req, res) {
if (req.session.login == null) {
// ログイン後に戻る値
req.session.back = '/boards';
res.redirect('/users/login');
return true;
} else {
return false;
}
}
// トップページ
router.get('/', (req, res, next) => {
res.redirect('/boards/0');
});
router.get('/:page',(req, res, next) => {
if (check(req, res)){ return };
const pg = req.params.page * 1;
db.Board.findAll({
offset: pg * pnum,
limit: pnum,
order: [
['createdAt', 'DESC']
],
include: [{
model: db.User,
required: true
}]
}).then(brds => {
var data = {
title: 'Boards',
login: req.session.login,
content: brds,
page: pg
}
res.render('boards/index', data);
});
});
// メッセージフォームの送信処理
router.post('/add', (req, res, next) => {
if (check(req, res)){ return };
db.sequelize.sync()
.then(() => db.Board.create({
userId: req.session.login.id,
message: req.body.msg
})
.then(brd => {
res.redirect('/boards');
})
.catch((err) => {
res.redirect('/boards');
})
)
});
// 利用者のホーム
router.get('/home/:user/:id/:page', (req,res, next) => {
if (check(req, res)){ return };
const id = req.params.id * 1;
const pg = req.params.page * 1;
db.Board.findAll({
where: {userId: id},
offset: pg * pnum,
limit: pnum,
order: [
['createdAt', 'DESC']
],
include: [{
model: db.User,
required: true
}]
}).then(brds => {
var data = {
title: 'Boards',
login: req.session.login,
userId: id,
userName: req.params.user,
content: brds,
page: pg
}
res.render('boards/home', data);
});
});
module.exports = router;
app.jsに組み込みます。
app.js
var boardsRouter = require('./routes/boards');
app.use('/boards', boardsRouter);
テンプレート作成
以下のファイルを作成します。
views/users/login.ejs
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="content-type" content="text/html">
<title><%= title %></title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" crossorigin="anonymous">
<link rel="stylesheet" href="/stylesheets/style.css" />
</head>
<body class="container">
<header>
<h1 class="display-4">
<%= title %>
</h1>
</header>
<div role="main">
<p><%- content %></p>
<form action="/users/login" method="post">
<div class="form-group">
<label for="name">NAME</label>
<input type="text" name="name" id="name" class="form-control">
</div>
<div class="form-group">
<label for="pass">PASSWORD</label>
<input type="text" name="pass" id="pass" class="form-control">
</div>
<input type="submit" value="ログイン" class="btn btn-primary">
</form>
<p class="mt-4"><a href="/boards"><< Top へ戻る</a>
<a href="/users/add">アカウントの作成>></a></p>
</div>
</body>
</html>
views/boards/index.ejs
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="content-type" content="text/html">
<title><%= title %></title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" crossorigin="anonymous">
<link rel="stylesheet" href="/stylesheets/style.css" />
</head>
<body class="container">
<header>
<h1 class="display-4">
<%= title %>
</h1>
</header>
<div role="main">
<p class="h4">Wlcome to <%= login.name %>.</p>
<form action="/boards/add" method="POST">
<div class="row">
<div class="col-10">
<input type="text" name="msg" class="form-control">
</div>
<input type="submit" value="送信" class="btn btn-primary col-2">
</div>
</form>
<table class="table mt-5">
<% for(let i in content) { %>
<%- include('data_item', {val: content[i]}) %>
<% } %>
</table>
<ul class="pagination justify-content-center">
<li class="page-item">
<a href="/boards/<%= page - 1 %>" class="page-link"><< prev</a>
</li>
<li class="page-item">
<a href="/boards/<%= page + 1 %>" class="page-link">Next >></a>
</li>
</ul>
</div>
</body>
</html>
views/boards/home.ejs
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="content-type" content="text/html">
<title><%= title %></title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" crossorigin="anonymous">
<link rel="stylesheet" href="/stylesheets/style.css" />
</head>
<body class="container">
<header>
<h1 class="display-4">
<%= title %>
</h1>
</header>
<div role="main">
<p class="h4"><%= userName %>'s messages.</p>
<table class="table mt-5">
<% for(let i in content) { %>
<%- include('data_item', {val: content[i]}) %>
<% } %>
</table>
<ul class="pagination justify-content-center">
<li class="page-item">
<a href="/boards/home/<%= userName %>/<%= userId %>/<%= page - 1 %>" class="page-link"><< prev</a>
</li>
<li class="page-item">
<a href="/boards/home/<%= userName %>/<%= userId %>/<%= page + 1 %>" class="page-link">Next >></a>
</li>
</ul>
</div>
<div class="text-left">
<a href="/boards"><< Top.</a>
</div>
</body>
</html>
views/boards/data_item.ejs
<% if (val != null) { %>
<tr class = "row">
<th class="col-2">
<a class="text-dark" href="/boards/home/<%=val.User.name %>/<%= val.userId %>/0">
<%= val.User.name %>
</a>
</th>
<td class="col-7"><%= val.message %></td>
<%
var d = new Date(val.createdAt);
var dstr = d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate() + ' ' + d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds();
%>
<td class="col-3"><%= dstr %></td>
</tr>
<% } %>