自分の分身を作りたい

理系の大学院生だよ

技術書共有アプリにユーザーのプロフィールを入力できるようにした。

ぜひフォローしてください

f:id:daigakukabuu:20181127192156p:plain 

これはPugのファビコンです。可愛いですね。

前回このよううな記事を書きました。

 

www.so-hack.com

 

この中で改良点として考えていた、ユーザープロフィールの編集を実装する

ということをやていこうと思います。

目次

プロフィール編集フォームの実装

まずはじめにプロフィールを編集する時の画面を作成します。

extends layout

block content
    h3.my-3 Edit Profile
    p #{geek.profile}
    form(method="post", action=`/users/${user.userId}?edit=1`)
        div.form-group
            label(for="profile") Your Profile
            textarea(name="profile" rows="4")#profile.form-control
        div.form-group
            button(type="submit").btn.btn-info Save

このアプリではテンプレートエンジンとしてExpressで動作するPugを利用しています。テンプレートエンジンを使うことで効率的にマークアップを行うことができます。

これでプロフィール設定画面にプロフィールを入力するためのテキストエリアとSaveボタンが実装されます。

Getting Started – Pug

コンテンツ部分以外のheadやbodyはすでに作成したlayout.pugにて他のページと共通のものを与えてあります。

doctype html
html
  head
    title= "Share Shelf"
    meta(charset="utf-8")
    meta(http-equiv="X-UA-Compatible" content="IE=edge")
    meta(name="viewport" content="width=device-width, initial-scale=1")
    link(rel='stylesheet', 
    href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css",
    integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm",
    crossorigin="anonymous")
    link(rel="stylesheet", type="text/css" href="stylesheets/style.css")
  
  body
    nav.navbar.navbar-light.bg-light
      div.navbar-header
        a(href="/").navbar-brand.nav-link Share Shelf
      ul.navbar-nav
        if user
          li.nav-item
            a(href="/logout").nav-link Sign out #{user.username} 
        else
          li.nav-item
            a(href="/login").nav-link Sign in
    div.container
      block content
    footer.fixed-bottom
      div.container
        p.text-muted Please sticky footer content here.
    script(src="/javascripts/bundle.js")

ハンドラをRouterオブジェクトに登録

次にこのページを開くためのハンドラをRouterオブジェクトに登録します。

users.js

//ルーティングを行う
router.get('/:userId/edit', authenticationEnsurer, (req, res, next) => {
    User.findOne({
        where: {
            userId: req.params.userId
        }
    }).then((user) => {
        if (isMine(req, user)) {
            res.render('profile', {
                user: user
            });
        } else {
            const err = new Error('You are not authorized to edit this profile');
            err.status = 404;
            next(err);
        }
    });
});

//ユーザー自身かを確認
function isMine(req, user) {
    return user && parseInt(user.userId) === parseInt(req.user.id);
}

URLからUserIdを拾ってUserデータからそのIdのユーザーを絞り込みそのデータを返します。

UserIdと今ログインしている人のIdを比較して、同じ場合は編集画面を開き、異なる場合はエラーを返すようにしました。

ここまでの段階で読み込んでみると、

f:id:daigakukabuu:20181127174733p:plain

編集画面を開くことができました。

編集を反映させる

次に編集したものを保存して反映できるようにします。

先ほどのusers.jsファイルにPOSTされた時のルーティング処理を追加します。

ユーザーのページを開きつつ、profileを更新しています。

router.post('/:userId', authenticationEnsurer, (req, res, next) => {
    console.log(req.body.profile);
    Book.findAll({
        where: {
            createdBy: req.params.userId
        },
        order: [['"updatedAt"', 'DESC']]
    }).then((books) => {
        if (books) {
            User.findOne({
                where: {
                    userId: req.params.userId
                }
            }).then((user) => {
                if (user && isMine(req, user)) {
                    if (parseInt(req.query.edit) === 1) {
                        user.update({
                            profile: req.body.profile
                        });
                        res.render('user', {
                            books: books,
                            //user: req.user,
                            user: user,
                            geekid: req.params.userId,
                            geek: user
                        });
                    } else {
                        const err = new Error('Bad request');
                        err.status = 400;
                        next(err);
                    }
                } else {
                    const err = new Error('You are not authorized');
                    err.status = 404;
                    next(err);
                }
            });
        console.log(req.params);
        } else {
            const err = new Error('Books not posted');
            err.status = 404;
            next(err);
        }
    });
});

f:id:daigakukabuu:20181127192029p:plain

こんな感じでプロフィールが表示されるようになりました。

ここにその人のやっていることや経歴を書けば、よりその人の本棚が参考になりますね!