Menu
CoddyTech

ネストされたルート

CoddyのNode.jsジャーニー「Expressの基礎」セクションの一部。レッスン 20/23。

レビューは1つのレシピに属するため、そのURLはレシピの配下にあります: /api/recipes/2/reviews。

const chapters = express.Router({ mergeParams: true });

chapters.get('/', (req, res) => {
    res.json(chaptersOf(req.params.isbn));
});

app.use('/api/books/:isbn/chapters', chapters);

ルーターの req.params には、そのルーター自身のパスのパラメーターのみが含まれます。マウントパスの :isbn はアプリに属するため、ルーター内では undefined になります。ただし、mergeParams: true を指定してルーターを作成した場合は除きます。

routes/reviews.js の準備ができており、reviews オブジェクトと hasRecipe(id) ヘルパーがあります。

challenge icon

チャレンジ

簡単

訪問者はレシピにレビューを投稿できます。レビューは1つのレシピに属するため、そのURLはレシピの下にあります: /api/recipes/1/reviews。

  1. routes/reviews.jsで、ルーターがマウントされているパスからレシピIDを読み取れるようにします。そうしないと、ルーター内のreq.params.idはundefinedになります(レッスンの説明を参照)。
  2. /のGETルートを追加します。対象レシピのレビューをJSONリストとして返し、まだレビューがない場合は空のリスト[]を返します。レビューはreviewsオブジェクトに保持し、レシピIDごとに1つのリストを用意します。例: { "1": [{ "stars": 5, "text": "Lovely" }] }。
  3. /のPOSTルートを追加します。本文からstarsとtextを読み取り、対象レシピのリストにレビューを追加して、ステータス201とレビューを返します: {"stars": 5, "text": "Lovely"}。この2つのフィールドだけを保存して送信します。
  4. 両方のルートで、hasRecipe(id)がfalseの場合は、ステータス404と{"error": "No such recipe"}を返します。
  5. server.jsでルーターをインポートし、レシピルーターの隣、404ハンドラーの前に、/api/recipes/:id/reviewsでマウントします。

試してみましょう:「実行」を押して、/api/recipes/1/reviewsを送信します: []。POSTを選び、{"stars": 5, "text": "Lovely"}を/api/recipes/1/reviewsに送信します: ステータス201とレビューが返ります。もう一度GETで/api/recipes/1/reviewsを送信します: [{"stars":5,"text":"Lovely"}]。/api/recipes/2/reviewsを送信します: 各レシピがそれぞれのレビューを保持するため、[]のままです。/api/recipes/99/reviewsを送信します: ステータス404と{"error":"No such recipe"}が返ります。

自分で試してみよう

import express from 'express';
import { recipes } from '../data.js';

// レシピの id ごとのレビュー。例: { 1: [{ stars: 5, text: 'Lovely' }] }。
const reviews = {};

const hasRecipe = (id) => recipes.some((recipe) => recipe.id === Number(id));

const router = express.Router();

// GET / はレシピのレビューを一覧表示します。POST / はレビューを1件追加します。

export default router;

Expressの基礎のすべてのレッスン

自分で練習してみよう: Expressプレイグラウンド