Menu
CoddyTech

PUTによる置き換え

CoddyのNode.jsジャーニー「REST API」セクションの一部。レッスン 5/25。

編集フォームはタスク全体を、すべてのフィールドをまとめて送り返します。PUT は「リソースをこれで置き換える」という意味なので、本文にはすべての内容が含まれていなければなりません。

PATCH /api/invoices/7  { "paid": true }               → paid changes
PUT   /api/invoices/7  { "amount": 90, "paid": true } → invoice 7 replaced
PUT   /api/invoices/7  { "paid": true }               → 400: amount missing

フィールドが欠けている PUT は 400 を返します。請求書の半分だけで置き換えると、金額が失われてしまうためです。id や作成時刻のようにサーバーが管理するフィールドは、本文からではなく、以前のバージョンから引き継ぎます。

const { id, issuedAt } = invoices[index];
invoices[index] = { id, amount, paid, issuedAt };
challenge icon

チャレンジ

簡単

編集フォームはタスク全体を一度に送り返します。クライアントから送られた内容でタスクを置き換える PUT ルートを追加しましょう。

  1. routes/tasks.js に PUT /api/tasks/:id を追加します。本文には、たとえば { "title": "Book the big room", "done": true } のように、両方のフィールドを含める必要があります。
  2. タスクの title と done を本文の値で置き換えます。保存済みのタスクにある id と createdAt はそのまま使い、本文から取得してはいけません。ステータス 200 とタスク全体を返します:
    { "id": 2, "title": "Book the big room", "done": true, "createdAt": "2026-03-03T10:30:00.000Z" }
  3. 本文に title または done がない場合は、ステータス 400 と { "error": "PUT needs every field: title and done" } を返し、何も変更しません。フィールドがないと判断するのは、本文にそのフィールド自体が存在しない場合だけです。"done": false は有効な値です。
  4. その ID のタスクがない場合は、他のルートと同様に、ステータス 404 と { "error": "Task not found" } を返します。

試してみましょう: PUT /api/tasks/2 に { "title": "Book the big room", "done": true } を送ると、200 と上記のタスクが返ります。次に、PUT /api/tasks/2 に { "done": true } だけを送ると 400 が返り、GET /api/tasks/2 では引き続き "Book the big room" と表示されます。PUT /api/tasks/99 に両方のフィールドを送ると 404 が返ります。

自分で試してみよう

import { Router } from 'express';
import { nextId, tasks } from '../store.js';

const router = Router();

router.get('/', (req, res) => {
    res.json(tasks);
});

router.get('/:id', (req, res) => {
    const task = tasks.find((t) => t.id === Number(req.params.id));
    if (!task) {
        return res.status(404).json({ error: 'Task not found' });
    }
    res.json(task);
});

router.post('/', (req, res) => {
    const { title } = req.body ?? {};
    if (!title) {
        return res.status(400).json({ error: 'title is required' });
    }
    const task = { id: nextId(), title, done: false, createdAt: new Date().toISOString() };
    tasks.push(task);
    res.status(201).location(`/api/tasks/${task.id}`).json(task);
});

router.patch('/:id', (req, res) => {
    const task = tasks.find((t) => t.id === Number(req.params.id));
    if (!task) {
        return res.status(404).json({ error: 'Task not found' });
    }
    const { title, done } = req.body ?? {};
    if (title !== undefined) task.title = title;
    if (done !== undefined) task.done = done;
    res.json(task);
});

router.delete('/:id', (req, res) => {
    const index = tasks.findIndex((t) => t.id === Number(req.params.id));
    if (index === -1) {
        return res.status(404).json({ error: 'Task not found' });
    }
    tasks.splice(index, 1);
    res.status(204).end();
});

export default router;
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

REST APIのすべてのレッスン

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