91日目:Post API Routesの作成:投稿の追加(put)と削除(delete)&like/unlikeの追加、Postmanでcollections作成

本日からSection5のPost API Routesの作成に入りました。珍しくスムーズに作業が進んで、ユーザーが投稿したテキストの追加と削除、それにlikeとunlikeの追加と削除のroutesが完成です。

今回使ったrequest は、POST・GET・DELETE・PUTです。前回、修正や復習をしたことでPostmanでのcollections作成にもかなり慣れてきて、間違えたとしてもすぐに気づくようになりました。少しずつは上達している感覚です。

Javascriptのmethodsについては、いくつかあやふやになっているものがあるので要復習です。

本日のコード①models/Post.js

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

const PostSchema = new Schema({
  user: {
    type: Schema.Types.ObjectId,
    ref: "users"
  },
  text: {
    type: String,
    required: true
  },
  name: {
    type: String
  },
  avatar: {
    type: String
  },
  likes: [
    {
      user: {
        type: Schema.Types.ObjectId,
        ref: "users" // to know which likes came from which user
      }
    }
  ],
  comments: [
    {
      user: {
        type: Schema.Types.ObjectId,
        ref: "users"
      },
      text: {
        type: String,
        required: true
      },
      name: {
        type: String
      },
      avatar: {
        type: String
      },
      date: {
        type: Date,
        default: Date.now
      }
    }
  ],
  date: {
    type: Date,
    default: Date.now
  }
});

module.exports = Post = mongoose.model("post", PostSchema);

本日のコード②routes/api/posts.js (次回コードを追加予定)

const express = require("express");
const router = express.Router();
const { check, validationResult } = require("express-validator/check");
const auth = require("../../middleware/auth");

const Post = require("../../models/Post");
const Profile = require("../../models/Profile");
const User = require("../../models/User");

// @route  POST api/posts
// @desc   Create a route
// @access Private
router.post(
  "/",
  [
    auth,
    [
      check("text", "Text is required")
        .not()
        .isEmpty()
    ]
  ],
  async (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }

    try {
      const user = await User.findById(req.user.id).select("-password");

      const newPost = new Post({
        text: req.body.text,
        name: user.name,
        avatar: user.avatar,
        user: req.user.id
      });

      const post = await newPost.save();

      res.json(post);
    } catch (error) {
      console.error(err.message);
      res.status(500).send("Server Error");
    }
  }
);

// @route  GET api/posts
// @desc   GET all posts
// @access Private
router.get("/", auth, async (req, res) => {
  try {
    const posts = await Post.find().sort({ date: -1 });
    res.json(posts);
  } catch (err) {
    console.error(err.message);
    res.status(500).send("Server Error");
  }
});

// @route  GET api/posts/:id
// @desc   GET post by ID
// @access Private
router.get("/:id", auth, async (req, res) => {
  try {
    const post = await Post.findById(req.params.id);

    if (!post) {
      return res.status(404).json({ msg: "Post not found" });
    }

    res.json(post);
  } catch (err) {
    console.error(err.message);
    if (err.kind === "ObjectId") {
      return res.status(404).json({ msg: "Post not found" });
    }
    res.status(500).send("Server Error");
  }
});

// @route  DELETE api/posts
// @desc   Delete a post
// @access Private
router.delete("/:id", auth, async (req, res) => {
  try {
    const post = await Post.findById(req.params.id);

    if (!post) {
      return resizeBy.status(404).json({ msg: "Post not found" });
    }

    //Check user = the person deleting a post is the user who posted
    if (post.user.toString() !== req.user.id) {
      return res.status(401).json({ msg: "User not authorized" });
    }

    await post.remove();

    res.json({ msg: "Post removed" });
  } catch (err) {
    console.error(err.message);
    if (err.kind === "ObjectId") {
      return res.status(404).json({ msg: "Post not found" });
    }
    res.status(500).send("Server Error");
  }
});

// @route  PUT api/like/:id
// @desc   Like a post
// @access Private
router.put("/like/:id", auth, async (req, res) => {
  try {
    const post = await Post.findById(req.params.id);

    //Check if the post has already been liked by this user
    //req.user.id = logged in user
    if (
      post.likes.filter(like => like.user.toString() === req.user.id).length > 0
    ) {
      return res.status(400).json({ msg: "Post already liked" });
    }

    post.likes.unshift({ user: req.user.id });

    await post.save();

    res.json(post.likes);
  } catch (err) {
    console.error(err.message);
    res.status(500).send("Server Error");
  }
});

// @route  PUT api/unlike/:id
// @desc   Like a post
// @access Private
router.put("/unlike/:id", auth, async (req, res) => {
  try {
    const post = await Post.findById(req.params.id);

    //Check if the post has already been liked by this user
    //req.user.id = logged in user
    //length === 0 means the post is not liked yet
    if (
      post.likes.filter(like => like.user.toString() === req.user.id).length ===
      0
    ) {
      return res.status(400).json({ msg: "Post has not yet been liked" });
    }

    // Get remove index
    const removeIndex = post.likes
      .map(like => like.user.toString())
      .indexOf(req.user.id);

    post.likes.splice(removeIndex, 1);

    await post.save();

    res.json(post.likes);
  } catch (err) {
    console.error(err.message);
    res.status(500).send("Server Error");
  }
});

module.exports = router;

次回は、このコードの中にコメントを追加&削除するRoutesのコードを書いていく予定です。それが終われば、このUdemyコースのバックエンド部分は終了となります。そこからReactを使ってフロントエンド部分を作成していく予定です。

本日書いたコードを元にPostmanでcollections作成:6 requests

本日書いたコードで作成できたcollectionsは以下のとおり。Web Developersがお互いにコミュニケーションを取ることができるWebサービスなので、テキストを投稿したり、Facebookのようにlike/unlikeができるようになっています。

①POST:Add Posts

②GET: Get all posts

③GET: Get post by ID

④DELETE: Delete posts

⑤PUT: Like post

⑥PUT: unlike post

先週、かなり間違いをして修正につぐ修正をしたおかげで、今回の作成は比較的スムーズでした。

現在使用している教材と学習時間:本日の学習時間2.0時間

Udemy:MERN Stack Front To Back: Full Stack React, Redux & Node.js by Brad Traversy

Section5: Post API Routes

-Lec24: Creating The Post Model

-Lec25: Add Post Route

-Lec26: Get& Delete Post Routes

-Lec27: Post Like & Unlike Routes(ここまで完了)

進捗状況:38%

学習時間2.0時間

~本日は休みにしている教材~

Udemy:The Complete Web Developer: Zero to Mastery by Andrei Neagoie

進捗状況: 92%

-参考にしたページ-

「express実践入門」小川充 (GitHub)

関連キーワード
  • 131日目~134日目:Udemyで一番人気のGit (&GitHub) コースを修了!学習した内容・学習にかかった時間とおすすめ度をご紹介: Completed Git course by Udemy "Git Complete: The definitive, step-by-step guide to Git" by Jason Taylor: Highly recommended to both beginner & intermediate leaner
  • 121日目~130日目:Udemyで新しいReactコース学習とGit & GitHubのコースを受講し始める #100dayofcode Round 2
  • 120日目:プログラミング学習100日チャレンジの完了とこれからの学習&ブログ記事:100days of code completed & from now on
  • 119日目:完成したWebアプリケーションの公開(Devconnector deployed on Heroku)
  • 118日目:Udemy講座の感想口コミ&自分に合った講座の選び方ポイント:Mern Stack Front to Back: Full Stack React, Redux & Node.js by Brad Traversy
  • 117日目:完成!Herokuへのデプロイ成功:Heroku CLIのインストールからWebアプリデプロイまで。Herokuの使い方と、package.jsonとgitコマンドではまったところと解決方法
おすすめの記事
【Javascript ES7 & React】constructorやsuper(); this.を使わないClassの新しい書き方: Classes&Properties & Methods【ES6との違い】
Javascript/React/Redux
ES7でのclassの書き方、 さらにmethods、 propertiesのコーディングについてまとめました。ES7では(ES6と違って)...