NodeJSにおけるMVCパターンの理解


これは、パート2の一部です、我々は我々の開発環境を準備して、我々の最初のテストを走らせました.このチュートリアルでは、MVCアーキテクチャを使用してエンドポイントを構築することに焦点を当てます.

用語の定義
モデルビューコントローラー
モデルビューコントローラは、アプリケーションロジックを3つの相互接続された要素、モデル、ビュー、およびコントローラに分離するソフトウェアアーキテクチャパターンです.
RESTful API
RESTは表現状態転送のための頭字語です、APIは他方、アプリケーション・プログラム・インターフェースの頭字語です.RESTful APIは、HTTPリクエストを使用してデータをアクセスして使用するアプリケーションプログラムインターフェイス(API)のアーキテクチャです.
私は、あなたがこのチュートリアルにかかわる用語に精通していると推測しました.始めましょう.
以前のチュートリアルでは、いくつかの依存関係を持つ非常に基本的なフォルダ構造を持っていました.API開発に必要な依存関係をインストールしましょう.
$ npm i --save-dev body-parser dotenv nodemon
インストール後、パッケージ.JSONファイルは以下のようになります.
{
  "name": "tdd-with-nodejs",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "jest",
    "start": "nodemon index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "body-parser": "^1.19.0",
    "dotenv": "^8.2.0",
    "express": "^4.17.1",
    "jest": "^26.6.3",
    "mongoose": "^5.11.9",
    "nodemon": "^2.0.6"
  }
}

NodeMonで実行する初期設定スクリプトを設定していますので、NodeMonは私たちのインデックスに対して行われた変更をすべて追跡します.JSファイルとそれに応じて我々のアプリケーションをリフレッシュします.次に、サーバを設定しましょう.** indexという名前のアプリケーションのルートディレクトリ内に新しいファイルを作成します.以下のコードをペーストします.
require('dotenv').config();
const mongoose =  require("mongoose");
//const articles = require("./routes/article.routes");
const bodyParser =  require("body-parser");

const app = exepress();
const port = 8000;

mongoose.connect(process.env.mongoURI, {useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true })
.then(res => console.log(`Connection Succesful ${res}`))
.catch(err => console.log(`Error in DB connection ${err}`));

//body-parser config;
app.use(exepress.json());
app.use(bodyParser.urlencoded({extended: true }));
app.use(bodyParser.json());

app.get("/", (req, res) => {
    res.send(`<h1>Hello!</h1>`)
});

app.listen(port, () => {
    console.log(`Application is listening at port ${port}`);
});

//register the enpoints
//app.use("/api/v1/articles", articles);

を作成することを忘れないでください.ENVファイルとそのようにデータベースURIを追加しますsrv://your-db-uri.次に、下記のコマンドを入力してアプリケーションを起動します.
$ npm run start
あなたの端末に対する応答を得るべきである:アプリケーションはポート8000 &接続が成功した[オブジェクトオブジェクト]を聞いている.あなたがhttp://localhost:8000を開くならば、あなたは「こんにちは!」画面にもログインします.
このチュートリアルでは、NVCパターンに適合するようにNonJSアプリケーションを適切に構成する方法を教えていますので、コントローラとルートファイルからビジネスロジックを分離します.我々は、このシリーズの最終的なチュートリアルである階層構造のチュートリアルでこれについての詳細を学びます.

モデルの構築
次に、モデルを作りましょう.プロジェクトのルートディレクトリ内に新しいフォルダーを作成し、フォルダに移動し、記事という名前の新しいファイルを作成します.JSとコピーをペーストして、APIのモデルを作成します.
const mongoose = require("mongoose");
const Schema = mongoose.Schema;


const articleSchema = Schema({

    title:{
        type: String,
        required: true,
    },

    body:{
        type: String,
        required: true,
    },

    article_image: {
        type: String,
        required: false,
    },

    date:{
        type: Date,
        default: Date.now(),
    }

});


module.exports = Article = mongoose.model("Article", articleSchema);
私たちのモデルは非常に基本的な、それはタイトル、体、および日付のオブジェクトがあります.MongoDBのスキーマを構築することについての詳細を学ぶことがマングースを使用して、公式doc hereを読んで.

記事サービスの構築
articleServiceを構築するにはJSは、サービスという名前のフォルダを作成して、我々のarticleserviceを収容する必要があります.jsファイル.以下のコードをあなたのarticleserviceにペーストします.js
const Article = require("../models/Article");

module.exports = class ArticleService{
    static async getAllArticles(){
        try {
            const allArticles = await  Article.find();
            return allArticles;
        } catch (error) {
            console.log(`Could not fetch articles ${error}`)
        }
    }

    static async createArticle(data){
        try {

            const newArticle = {
                title: data.title,
                body: data.body,
                article_image: data.article_image
            }
           const response = await new Article(newArticle).save();
           return response;
        } catch (error) {
            console.log(error);
        } 

    }
    static async getArticlebyId(articleId){
        try {
            const singleArticleResponse =  await Article.findById({_id: articleId});
            return singleArticleResponse;
        } catch (error) {
            console.log(`Article not found. ${error}`)
        }
    }

    static async updateArticle(title, body, articleImage){
            try {
                const updateResponse =  await Article.updateOne(
                    {title, body, articleImage}, 
                    {$set: {date: new Date.now()}});

                    return updateResponse;
            } catch (error) {
                console.log(`Could not update Article ${error}` );

        }
    }

    static async deleteArticle(articleId){
        try {
            const deletedResponse = await Article.findOneAndDelete(articleId);
            return deletedResponse;
        } catch (error) {
            console.log(`Could  ot delete article ${error}`);
        }

    }
}

コントローラのビルド
次に、私たちのAPIエンドポイントを書き始め、コントローラという名前のルートディレクトリ内の新しいフォルダを作成し、フォルダに移動し、記事という名前の新しいファイルを作成します.コントローラ.js以下のコードをペーストします.
const ArticleService = require("../services/ArticleService");

module.exports = class Article{

   static async apiGetAllArticles(req, res, next){
       try {
         const articles = await ArticleService.getAllArticles();
         if(!articles){
            res.status(404).json("There are no article published yet!")
         }
         res.json(articles);
       } catch (error) {
          res.status(500).json({error: error})
       }

   }

   static async apiGetArticleById(req, res, next){
      try {
         let id = req.params.id || {};
         const article = await ArticleService.getArticlebyId(id);
         res.json(article);
      } catch (error) {
         res.status(500).json({error: error})
      }
   }

   static async apiCreateArticle(req, res, next){
      try {
         const createdArticle =  await ArticleService.createArticle(req.body);
         res.json(createdArticle);
      } catch (error) {
         res.status(500).json({error: error});
      }
   }

   static async apiUpdateArticle(req, res, next){
      try {
         const comment = {}
         comment.title        = req.body.title;
         comment.body         = req.body.body;
         comment.articleImage = req.body.article_image

         const updatedArticle = await ArticleService.updateArticle(comment);

         if(updatedArticle.modifiedCount === 0){
            throw new Error("Unable to update article, error occord");
         }

         res.json(updatedArticle);

      } catch (error) {
         res.status(500).json({error: error});
      }
   }

   static async apiDeleteArticle(req, res, next){
         try {
            const articleId = req.params.id;
            const deleteResponse =  await ArticleService.deleteArticle(articleId)
            res.json(deleteResponse);
         } catch (error) {
            res.status(500).json({error: error})
         }
   }

}


ルートを構築する
我々の終点と通信するために、我々は対応する要請で我々のルートを準備する必要があります.ルートという名前の新しいフォルダを作成し、フォルダ内に記事という名前の新しいファイルを作成します.路線jsあなたは好きなフォルダを名前を選択することができますが、それは常に意味のあるディレクトリとファイル名を維持するのに良いです.
const  express =  require("express");
const router = express.Router();
const ArticleCtrl = require("../controllers/article.controller");


router.get("/", ArticleCtrl.apiGetAllArticles);
router.post("/", ArticleCtrl.apiCreateArticle);
router.get("/article/:id", ArticleCtrl.apiGetArticleById);
router.put("/article/:id", ArticleCtrl.apiUpdateArticle);
router.delete("/article/:id", ArticleCtrl.apiDeleteArticle);

module.exports =  router;
あなたがこの点までチュートリアルに従ったならば、あなたのフォルダ構造は実は以下のスニペットのように見えなければなりません.
├── tdd-with-nodejs
 ├── controllers
     ├── article.controller.js
 ├── models
     ├── Article.js
 ├── routes
     ├── article.routes.js
 ├── services
     ├── articleService.js
├── test

すべてをまとめる
MVCパターンで作業するときは、常にあなたが関心事(SoC)技術の分離を維持することを確認します.関心の分離(SOC)は、各セクションが別々の懸念に対処するように、ソフトウェアアプリケーションを別個のセクションに分離するための設計原理である.懸念は、ソフトウェアアプリケーションのコードに影響する情報のセットです.我々は、このシリーズの最後である次のチュートリアルでは、このトピックに深く潜入します.
結論を出す前に、エンドポイントの1つをテストしましょう.APIのテストツールを使用して/API/V 1/記事のエンドポイントにポストリクエストを送信します.私の場合では、Postmanは、以下のスニペットに似た新しく作成された記事のレスポンスとしてレスポンスオブジェクトを取得する必要があります.

これはすべてこのチュートリアルです.このシリーズでそれを作ることにおめでとう.次のチュートリアルを参照してください.