1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

node.js実践編(メッセージボード編)

Last updated at Posted at 2021-09-09

※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">&lt;&lt; Top へ戻る</a>
                <a href="/users/add">アカウントの作成&gt;&gt;</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">&lt;&lt; prev</a>
                </li>
                <li class="page-item">
                    <a href="/boards/<%= page + 1 %>" class="page-link">Next &gt;&gt;</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">&lt;&lt; prev</a>
                </li>
                <li class="page-item">
                    <a href="/boards/home/<%= userName %>/<%= userId %>/<%= page + 1 %>" class="page-link">Next &gt;&gt;</a>
                </li>
            </ul>
        </div>
        <div class="text-left">
            <a href="/boards">&lt;&lt; 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>
<% } %>

結果

ログイン画面

image.png

メッセージボード画面

image.png

ユーザーのホーム画面

image.png

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?