NestJSでAPIを書いてみよう![はじめてのAPI実装 第2回]

Share
目次
カテゴリのアイコン カテゴリ一覧 NestJS

NestJSでAPIを書いてみよう![はじめてのAPI実装 第2回]

NestJSでAPIを書いてみよう![はじめてのAPI実装 第2回]

更新日

はじめに

前回の【APIとは?】実装に最低限必要な知識をまとめました[はじめてのAPI実装 第1回]」では、APIの基本概念や最低限必要な知識について解説しました。

APIとは何かCRUD操作HTTPメソッドの関係性、そしてAPIを実装する際におすすめのフレームワークであるNestJSの概要について学びました。

もし、「APIって何?」「NestJSって何?」という方は、ぜひ前回の記事をご覧ください。基礎的な知識を押さえておくことで、今回の内容がより理解しやすくなります。

あわせて読みたい

今回は、前回の内容を踏まえて、NestJSの具体的なコードを見ながら、その仕組みを理解し、実際にAPIを実装していきます。NestJSの基本構造であるコントローラー、サービス、モジュールについて学び、それらを組み合わせてシンプルなCRUD機能を持つAPIを作成します。

この記事を読むことで得られること

  • NestJSの基本的なコード構造と役割を理解できる
  • 実際にAPIを実装する手順を学べる
  • CRUD機能を持つAPIを作成し、動作を確認できる

想定読者

  • 前回の記事を読んだ方、またはAPIとNestJSの基本を理解している方
  • NestJSを使ってAPIを実装してみたい方
  • 実践的なコードを通じて学習したい方

NestJSの実際のコードを覗いてみよう!

NestJSにはコントローラー、サービス、モジュールという基本的なアーキテクチャがあります。

まずは、シンプルなコントローラー、サービス、モジュールの実際のコードを見ながら、これらの役割についてイメージを深めていきましょう。

コントローラー(Controller)

コントローラーは、クライアントからのリクエストを受け取り、レスポンスを返す役割を持っています。以下に簡単なコントローラーの例を示します。

import { Controller, Get } from '@nestjs/common';

@Controller('members')
export class MembersController {
  @Get()
  findMembers(): string {
    return '全てのメンバーを取得します';
  }
}

コードの解説

1.@Controller(‘members’)
このクラスをコントローラーとして機能させるためのデコレータです。
‘members’を指定することで、このコントローラーがhttps://hipnoclub.com/membersというURLエンドポイントに対応します。

2.@GET( )デコレータ
HTTPのGETリクエストに対応するメソッドを示します。
ここでは、/membersにGETリクエストが送られたとき、findMembersメソッドが呼び出されます。

3.findMembersメソッド
クライアントからリクエストを受け取ると、文字列「全てのメンバーを取得します」をレスポンスとして返します。

このコードの問題点

現在のコントローラーの実装は非常にシンプルですが、NestJSのアーキテクチャにおける責務の分離の観点からみると以下の問題があります。

1.コントローラーが直接データ処理を行っている
コントローラーの役割は、リクエストを受け取り、適切なサービスを呼び出して処理を委譲し、その結果をレスポンスとして返すことです。しかし、このコードではレスポンスとして返す内容(’全てのメンバーを取得します’)をコントローラー内で定義しています。

2.ビジネスロジックの分離が不十分
データの処理やビジネスロジックは、コントローラーではなく、サービス(Service)で実装すべきです。これにより、コードの可読性と再利用性が向上します。

コントローラーを改善する

以下のように、データ処理部分をサービスに委譲することで、コントローラーの役割を明確化できます。

import { Controller, Get } from '@nestjs/common';
import { MembersService } from './members.service';

@Controller('members')
export class MembersController {
  constructor(private readonly membersService: MembersService) {}

  @Get()
  findMembers(): string {
    return this.membersService.findMembers();
  }
}

改善のポイント

1.サービスの注入
コンストラクターにMembersServiceを記述することで、コントローラーはサービスを利用できるようになります。この仕組みを依存性注入(Dependency Injection)と呼び、NestJSが自動でサービスを利用できるようにしてくれます。

2.コントローラーの責務を限定
コントローラーはリクエストを受け取り、サービスを呼び出し、結果をレスポンスとして返すだけの役割になります。

3.データ処理をサービスに委譲
コントローラーはデータ処理の責任をサービスに委譲します。具体的には、サービスの注入により利用できるようになったthis.membersService.findMembers()MemberServiceクラス内に定義されたfindMembersメソッドを呼び出し、その処理結果をクライアントに返しています。

サービス(Service)

先ほど、リクエストの窓口であるコントローラーの実装を見てきました。ここでは、受け取ったリクエストに応じてどのようなデータの処理を行うのかを定義するサービスを見ていきましょう。
以下はシンプルなサービスの例です。

import { Injectable } from '@nestjs/common';

@Injectable()
export class MembersService {
  findMembers() {
    const message = '全てのメンバーを取得します';
    return message;
  }
}

コードの解説

1.@Injectable( )デコレーター
このデコレータをクラスに付与することで、NestJSにこのクラスが「サービス」として機能することを知らせます。また、他のクラス(例えば、コントローラー)から注入して利用できるようになります。

2.findMembers( )メソッド
このメソッドは、全てのメンバー情報を取得する処理を担当します。現在は簡単な文字列を返すだけですが、実際のアプリケーションではデータベースから情報を取得するロジックがここに含まれます。

サービスの役割

サービスは、アプリケーションのビジネスロジックやデータ処理を担当します。コントローラーと組み合わせて動作し、以下のような利点を提供します。

1.ビジネスロジックの集中管理
データの取得、加工、保存といった複雑なロジックをサービスにまとめることで、コントローラーをシンプルに保てます。

2.コードの再利用性
サービスを他のコントローラーでも利用できるため、コードの再利用性が高まります。

モジュール(Module)

これまで、コントローラーの実装とサービスの実装について学んできました。コントローラーはリクエストを受け取り、レスポンスを返す役割を持ち、サービスはその処理内容を担っています。これらは組み合わせることで1つの機能(API)を成します。

しかし、現在の状態ではコントローラーとサービスはそれぞれ別々のファイルに記述された、何のつながりもない独立したコードです。ここで登場するのがモジュールです。

モジュールは、コントローラーとサービスを紐づけ、一体化させる役割を果たします。モジュールを利用することで、アプリケーション内の機能を整理し、管理しやすくなります。
以下はシンプルなモジュールの例です。

import { Module } from '@nestjs/common';
import { MembersController } from './members.controller';
import { MembersService } from './members.service';

@Module({
  controllers: [MembersController],
  providers: [MembersService],
})
export class MembersModule {}

コードの解説

1.@Module( )デコレーター
モジュールを定義するためのデコレーターです。@Module( )の中に、モジュールが持つコントローラーやプロバイダー(サービスなど)を登録します。

2.controllersプロパティ
このモジュールが管理するコントローラーを指定します。ここではMembersControllerが登録されています。

3.providersプロパティ
このモジュールが管理するプロバイダー(サービスなど)を指定します。ここではMembersServiceが登録されています。

4.MembersModuleクラス
@Module( )デコレーターを付与されたこのクラスが、NestJSにおけるモジュールとして機能します。

モジュールの役割

モジュールは以下のような役割を持っています。

1.機能ごとのグループ化
モジュールは、関連するコントローラーやサービスを1つのまとまりとして管理するための単位です。これにより、アプリケーション全体の構造が整理され、特定の機能に関するコードが見つけやすくなります。例えば、MembersModuleにはメンバーに関するコントローラーとサービスが集約されています。このように、機能単位でコードをグループ化することで、規模が大きなプロジェクトでも管理しやすくなります。

2.依存関係の管理
モジュールには、コントローラーやサービス間の依存関係を明示的に記述します。これにより、必要なサービスが正しく注入され、機能が正常に動作するようになります。例えば、MembersControllerMembersServiceに依存していますが、モジュールを通じてこの依存関係が自動的に管理されるため、コントローラーが適切にサービスを利用できるようになります。

NestJSで開発の準備をしよう!

これまで、APIの基本とNestJSの魅力について学び、開発のイメージが少しずつ掴めてきたのではないでしょうか?この章では、NestJSを使ったAPI開発の第一歩として、開発環境を整え、プロジェクトの初期設定を進めていきます。難しい部分はありませんので、リラックスして進めてください。

NestJSの開発環境を整えよう

まず、NestJSで開発を進めるために必要なツールを準備します。
以下のツールをインストールしてください。

1.Node.js
NestJSはNode.js上で動作します。公式サイトから最新のLTSバージョンをインストールしてください。。インストール後、以下のコマンドでバージョンを確認します。

$ node -v
$ npm -v

2.Postman
作成したAPIの動作確認を行うために必要です。Postman公式サイトからダウンロードし、インストールしてください。

Nest CLIをインストールしてプロジェクトを作成しよう

Nest CLIとは、NestJSのプロジェクト作成や管理を効率的に行うための公式ツールです。CLIは「コマンドラインインターフェース」の略で、このCLIを使うことで、プロジェクト作成やコントローラーやサービスなどの生成、それらの依存関係の設定を自動で行うことができます。

1.Nest CLIをインストール
ターミナルを開き、以下のコマンドを実行します。

$ npm install -g @nestjs/cli

2.バージョン確認
正常にインストールされたか確認するために、以下のコマンドを実行します。

$ nest -v

3.プロジェクトを作成
次にNest CLIを使って新しいプロジェクトを作成します。

$ nest new hipnoclub

プロジェクト名には自由な名前を付けて構いません。ここではhipnoclubとしています。

作成したプロジェクトの中身を整理しよう

プロジェクトが作成されたら、エディタでプロジェクトを開いてみてください。Nest CLI によって、NestJS を実行するための環境が自動的に作成されています。

これから、実際に API のコードを記述していくのは srcフォルダ内です。まずは srcフォルダを開いて、どのようなファイルが生成されているか確認してみましょう。

src/
├── app.controller.spec.ts
├── app.controller.ts
├── app.module.ts
├── app.service.ts
└── main.ts

これらのファイルは、Nest CLI がプロジェクト作成時に自動生成したもので、サンプルのコントローラーやサービスが含まれています。しかし、今回は一から自分で実装していくため、不要なファイルを削除してプロジェクトを整理しましょう。

以下のファイルを削除してください
● app.controller.spec.ts (テストファイル)
● app.controller.ts (サンプルのコントローラー)
● app.service.ts (サンプルのサービス)

削除後のsrcフォルダは次のようになります。

src/
├── app.module.ts
└── main.ts

これでプロジェクトがすっきりしました。次に、app.module.ts ファイルを開いて、中身を以下のように修正します。これは、削除したファイルに関する記述を取り除くためです。

// src/app.module.ts

import { Module } from '@nestjs/common';

@Module({
  imports: [],
  controllers: [],
  providers: [],
})
export class AppModule {}

app.module.tsの中から、AppControllerやAppServiceに関するインポートや設定を削除しました。

main.tsと app.module.ts の役割を理解しよう

main.ts

// src/main.ts

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(process.env.PORT ?? 3000);
}
bootstrap();

main.tsはアプリケーションのエントリーポイントです。NestJSが起動すると、まずこのファイルが実行されます。await NestFactory.create(AppModule); で、AppModule がmain.tsに紐づいていることが確認できます。

app.module.ts

// src/app.module.ts

import { Module } from '@nestjs/common';

@Module({
  imports: [],
  controllers: [],
  providers: [],
})
export class AppModule {}

AppModuleはアプリケーションのルートモジュールです。NestJSはこのモジュールを起点に、アプリケーション全体の依存関係を構築します。

アプリケーションが小規模であれば、このAppModule だけで全ての機能を定義することも可能です。しかし、アプリケーションが大きくなると、機能ごとにモジュールを分割することでコードの管理がしやすくなります。

例えば、これまで見てきたようにMembersControllerとMembersServiceは連携して1つの機能を提供します。これらをMembersModuleに登録することで、両者が紐づき、具体的な機能(API)として動作する仕組みが整います。

さらに、MemberModuleをルートモジュールであるapp.module.tsに登録することで、アプリケーション全体にその機能が組み込まれ、最終的にmain.tsから起動される形になります。

ヒプノクラブのアプリケーションには、メンバーに関する機能以外にも様々な機能が考えられます。例えば、イベントを管理する機能や、メンバー同士がチャットで交流できる機能などです。

これらの機能は、それぞ専用のモジュールとして分けられます。EventsModule、ChatModuleなどが作成され、必要に応じてapp.module.tsに登録されることで、ヒプノクラブアプリケーションとして1つに統合されます。

// src/app.module.ts

import { Module } from '@nestjs/common';
import { MembersModule } from './members/members.module';
import { EventsModule } from './events/events.module';
import { ChatModule } from './chat/chat.module';

@Module({
  imports: [MembersModule, EventsModule, ChatModule],
  controllers: [],
  providers: [],
})
export class AppModule {}

この辺りは少し難しく感じるかもしれませんが、Nest CLIが自動で設定してくれるので、そこまで心配する必要はありません。説明を読み進めながら、main.tsやapp.module.tsのイメージを掴んでいきましょう。

メンバー登録APIを実装する!

さて、ここまで読み進めてきた皆さんは、APIを実装する準備が整いました。いよいよ、実際にコードを書きながら、APIの実態を捉えていきましょう!

Nest CLIでモジュール・コントローラー・サービスを作成

まずは、Nest CLIを使ってメンバーに関するモジュールコントローラーサービスを作成していきます。ここで、Nest CLIの便利さを実感できると思います。

モジュールを作成

$ nest generate module members

このコマンドを実行すると、src ディレクトリ配下members ディレクトリが作成され、その中に members.module.ts ファイルが生成されます。

さらに、ルートモジュールである AppModule imports 配列MembersModule が自動で登録されます。app.module.ts を確認してみましょう。

// src/app.module.ts

import { Module } from '@nestjs/common';
import { MembersModule } from './members/members.module';

@Module({
  imports: [MembersModule],
  controllers: [],
  providers: [],
})
export class AppModule {}

コントローラーを作成

$ nest generate controller members --no-spec

–no-specテストファイル(.spec.ts)を作成しないオプションです。このコマンドを実行すると、members ディレクトリ内members.controller.ts が生成されます。

// src/members/members.controller.ts

import { Controller } from '@nestjs/common';

@Controller('members')
export class MembersController {}

@Controller(‘members’) デコレーターにより、このコントローラーが /members というパスに紐づけられていることがわかります。

また、members.module.ts を開くと、MembersController が自動でモジュールに登録されていることが確認できます。

// src/members/members.module.ts

import { Module } from '@nestjs/common';
import { MembersController } from './members.controller';

@Module({
  controllers: [MembersController],
  providers: [],
})
export class MembersModule {}

サービスを作成

$ nest generate service members --no-spec

このコマンドを実行すると、members ディレクトリ内members.service.ts が生成されます。

// src/members/members.service.ts

import { Injectable } from '@nestjs/common';

@Injectable()
export class MembersService {}

再度、members.module.ts を確認すると、MembersService がモジュールに登録されています。

// src/members/members.module.ts

import { Module } from '@nestjs/common';
import { MembersController } from './members.controller';
import { MembersService } from './members.service';

@Module({
  controllers: [MembersController],
  providers: [MembersService],
})
export class MembersModule {}

メンバーモデルの作成

メンバー登録APIを実装する前に、メンバーモデルを作成しておきましょう。これは、メンバーのデータ構造(型定義)を明確にするためのものです。TypeScriptの型定義を使用することで、データの一貫性と安全性を確保できます。

今回は、メンバーの情報として以下の項目を扱います。
● id(ID)
● name(名前)
● age(年齢)
● email(メールアドレス)

members ディレクトリ内member.model.ts ファイルを作成し、以下のコードを記述してください。

// src/members/member.model.ts

export interface Member {
  id: number;
  name: string;
  age: number;
  email: string;
}

Member インターフェースは、メンバーオブジェクトの型を定義しています。これにより、メンバーのデータが期待した構造になっているかを型チェックできます。

メンバー登録APIのサービスを実装

次に、メンバーを登録するためのサービスを実装します。MembersService クラスにメンバーのデータを管理するロジックを追加します。

// src/members/members.service.ts

import { Injectable } from '@nestjs/common';
import { Member } from './member.model';

@Injectable()
export class MembersService {
  private members: Member[] = [];

  createMember(member: Member): Member {
    this.members.push(member);
    return member;
  }
}

コードの解説

1.private members: Member[] = [];
members というプライベートな配列を作成し、Member 型の要素を持つように定義しています。この配列が、メンバー情報を一時的に保存する場所となります。現時点ではデータベースを使用していないため、メモリ上の配列にデータを保存しています。

2.createMember(member: Member): Member
メソッドが呼び出されると、引数として受け取った member オブジェクトを members 配列に追加します。returnで、追加した member オブジェクトをそのまま返します。これにより、コントローラーから呼び出した際に、登録されたメンバー情報をレスポンスとして返すことができます。

メンバー登録APIのコントローラーを実装

続いて、メンバー登録のリクエストを受け取るコントローラーを実装します。

// src/members/members.controller.ts

import { Body, Controller, Post } from '@nestjs/common';
import { MembersService } from './members.service';
import { Member } from './member.model';

@Controller('members')
export class MembersController {
  constructor(private readonly membersService: MembersService) {}

  @Post()
  createMember(
    @Body('id') id: number,
    @Body('name') name: string,
    @Body('age') age: number,
    @Body('email') email: string,
  ): Member {
    const member: Member = {
      id,
      name,
      age,
      email,
    };
    return this.membersService.createMember(member);
  }
}

コードの解説

1.constructor(private readonly membersService: MembersService) { }
コントローラーのコンストラクターで MembersService を受け取り、クラス内で使用できるようにしています。NestJSの依存性注入(DI)機能により、サービスのインスタンスが自動的に提供されます。

2.@Post( ) デコレーター
@Post( ) デコレーターを付けることで、このメソッドが HTTPのPOSTリクエストに対応することを示しています。クラスレベルの @Controller(‘members’) と組み合わせると、/members のパスに対するPOSTリクエストがこのメソッドで処理されます。

3.@Body( ) デコレーター
@Body( )デコレーターはリクエストボディからデータを取得します。@Body(‘キー名’) とすることで、リクエストのボディから特定のキーの値を取得できます。ここでは、id, name, age, email をそれぞれ取得し、対応する変数に格納しています。

4.Member インターフェースの使用
取得したデータを元に、Member 型のオブジェクト member を作成しています。Memberインターフェースを使用することで、オブジェクトの構造が明確になり、型チェックが行われます。

5.サービスへの処理委譲
this.membersService.createMember(member)により、作成した member オブジェクトを MembersService の createMember メソッドに渡しています。データの保存などのビジネスロジックはサービスに任せ、コントローラーはリクエストの受け取りとレスポンスの返却に専念します。

Postmanでメンバー登録APIを検証

実装したメンバー登録APIが正しく動作するか、Postmanを使ってテストしてみましょう。

アプリケーションを起動

まず、ターミナルでアプリケーションを起動します。

$ npm run start:dev

Postmanで新しいリクエストを作成

1.新規リクエストの作成
Postmanを開き、「新規リクエストを作成」で「HTTPリクエスト」を作成します。

2.リクエストの設定
● HTTPメソッド: POSTを選択
● URL: http://localhost:3000/members

3.ボディの設定
● x-www-form-urlencodedを選択
● キーと値を下記の表のように記入

キー
id1
nameTanaka
age30
emailtanaka@example.com

リクエストの送信

「送信」ボタンをクリックしてリクエストを送信します。

レスポンスの確認

● ステータスコード: 201 Createdが返ってくれば成功です。
● レスポンスボディ: 送信したメンバー情報がそのまま返ってくるはずです。

{
    "id": "1",
    "name": "Tanaka",
    "age": "30",
    "email": "tanaka@example.com"
}

複数回テストしてみる

別のメンバー情報を入力して、再度リクエストを送信してみましょう。

キー
id2
nameSato
age28
emailsato@example.com

無事にレスポンスが返ってきたら、メンバー登録APIは完成です。

ここまで取り組んでみて、APIの仕組みや実装方法が具体的に理解できたのではないでしょうか。この調子で、メンバー一覧取得API、メンバー更新API、メンバー削除APIも実装してみましょう!

メンバー一覧取得APIを実装する!

前章ではメンバー登録APIを実装しましたね。今回は、登録されたメンバーの一覧を取得するAPIを作成します。これにより、登録されたメンバー情報を一括で取得できるようになります。

メンバー一覧取得APIのサービスを実装

まず、登録されたメンバーの一覧を取得するためのサービスメソッドを追加します。MembersService クラスに以下のコードを追加しましょう。

// src/members/members.service.ts

import { Injectable } from '@nestjs/common';
import { Member } from './member.model';

@Injectable()
export class MembersService {
  private members: Member[] = [];

  findMembers(): Member[] {
    return this.members;
  }
}

コードの解説

findMembers( ) メソッドを作成し、members 配列に格納された全てのメンバー情報を返します。

メンバー一覧取得APIのコントローラーを実装

次に、メンバー一覧取得のリクエストを処理するためのコントローラーメソッドを追加します。

// src/members/members.controller.ts

import { Controller, Get } from '@nestjs/common';
import { MembersService } from './members.service';
import { Member } from './member.model';

@Controller('members')
export class MembersController {
  constructor(private readonly membersService: MembersService) {}

  @Get()
  findMembers(): Member[] {
    return this.membersService.findMembers();
  }
}

コードの解説

1.@Get() デコレーター
このメソッドが HTTPのGETリクエスト に対応することを示します。

2.findMembers() メソッド
サービスの findMembers() メソッドを呼び出し、メンバー一覧を取得します。

Postmanでメンバー一覧取得APIを検証

実装したメンバー一覧取得APIが正しく動作するか、Postmanを使ってテストしてみましょう。

アプリケーションを起動

ターミナルでアプリケーションを起動します。

Postmanでメンバーを登録

現在、データベースを使用していないため、メンバー情報はサーバーのメモリ上に保存されています。サーバーを再起動するとデータはリセットされます。そのため、メンバー一覧を取得する前に、メンバー登録APIを使ってメンバーを登録しておきましょう。

例として下記の2人のメンバーを登録します。

キー
id1
nameTanaka
age30
emailtanaka@example.com
キー
id2
nameSato
age28
emailsato@example.com

メンバー一覧取得のリクエストを作成

1.新しいリクエストを作成
● HTTPメソッド: GET
● URL: http://localhost:3000/members

2.リクエストを送信
「送信」ボタンをクリックしてリクエストを送信します。

レスポンスの確認

● ステータスコード: 200 OKが返ってくれば成功です。
● レスポンスボディ: 先ほど登録したメンバー情報の一覧が返ってきます。

[
  {
    "id": 1,
    "name": "Tanaka",
    "age": 30,
    "email": "tanaka@example.com"
  },
  {
    "id": 2,
    "name": "Sato",
    "age": 28,
    "email": "sato@example.com"
  }
]

メンバー更新APIを実装する!

これまでに、メンバーの登録と一覧取得ができるようになりました。次は、既存のメンバー情報を更新するAPIを実装してみましょう。

メンバー更新APIのサービスを実装

まず、メンバー情報を更新するためのサービスメソッドを追加します。MembersService クラスに以下のコードを追加してください。

// src/members/members.service.ts

import { Injectable } from '@nestjs/common';
import { Member } from './member.model';

@Injectable()
export class MembersService {
  private members: Member[] = [];

  updateMember(member: Member): Member {
    const index = this.members.findIndex((m) => m.id === member.id);
    if (index !== -1) {
      this.members[index] = member;
      return member;
    }
    return null;
  }
}

コードの解説

updateMember(member: Member): Member メソッド
引数として受け取った member オブジェクトを使って、既存のメンバー情報を更新します。

処理の流れ
1. this.members.findIndex((m) => m.id === member.id)
members 配列内で、更新対象のメンバー(id が一致するメンバー)のインデックスを検索します。

2.存在チェックと更新
指定されたidのメンバーが存在する場合は、配列内の該当インデックスにあるメンバー情報を、新しい member オブジェクトで上書きして、更新したメンバー情報を返します。

this.members[index] = member;
return member;

3.メンバーが存在しない場合
null を返します。これは、指定された id のメンバーが見つからなかったことを示します。

メンバー更新APIのコントローラーを実装

次に、メンバー更新のリクエストを処理するコントローラーメソッドを追加します。

// src/members/members.controller.ts

import { Body, Controller, Param, Put } from '@nestjs/common';
import { MembersService } from './members.service';
import { Member } from './member.model';

@Controller('members')
export class MembersController {
  constructor(private readonly membersService: MembersService) {}

  @Put(':id')
  updateMember(
    @Param('id') id: number,
    @Body('name') name: string,
    @Body('age') age: number,
    @Body('email') email: string,
  ): Member {
    const member: Member = {
      id,
      name,
      age,
      email,
    };
    return this.membersService.updateMember(member);
  }
}

コードの解説

1.@Put(‘:id’) デコレーター
このメソッドがHTTPのPUTリクエストに対応することを示します。:id の部分はコロン(:)を付けることで、URLの一部をパラメータとして扱います。ここでは、/members/1 のようにリクエストが来た場合、id は 1 となります。

2.@Param(‘id’) id: number
@Param( ) デコレーターは、URLパラメータから値を取得するために使用します。’id’と記述することにより、取得したいパラメータのキー名を指定します。ここでは :id に対応しています。
id: number: 取得したパラメータを number 型の変数 id として受け取ります。

3.メンバーオブジェクトの作成
取得した id, name, age, email を使って、新しい Member オブジェクトを作成します。
これが更新後のメンバー情報となります。

4.サービスへの処理委譲

作成したメンバーオブジェクトをサービスの updateMember メソッドに渡して、更新処理を実行します。サービスで実装したように、戻り値は更新されたメンバー情報となります。もし更新に失敗した場合は null が返ります。

Postmanでメンバー更新APIを検証

メンバーを登録

これまで行ってきた通り、更新対処となるメンバーを登録しましょう。例として下記のメンバーを登録します。

キー
id1
nameTanaka
age30
emailtanaka@example.com

メンバー更新のリクエストを作成

1.新しいリクエストを作成
● HTTPメソッド: PUT
● URL: http://localhost:3000/members/1(1 は更新したいメンバーのIDです)

2.ボディの設定
● x-www-form-urlencodedを選択
● キーと値を下記のように記入
nameTanaka Taroに、age31に、emailtanaka2@example.comに更新してみましょう。

キー
nameTanaka Taro
age31
emailtanaka2@example.com

3.リクエストを送信
「送信」ボタンをクリックしてリクエストを送信します。

レスポンスの確認

● ステータスコード: 200 OKが返ってくれば成功です。
● レスポンスボディ: 先ほど更新した情報が返ってきます。

{
    "id": "1",
    "name": "Tanaka Taro",
    "age": "31",
    "email": "tanaka2@example.com"
}

メンバー削除APIを実装する!

これまでに、メンバーの登録、一覧取得、更新ができるようになりました。最後に、メンバーを削除するAPIを実装してみましょう。

メンバー削除APIのサービスを実装

まず、メンバーを削除するためのサービスメソッドを追加します。MembersService クラスに以下のコードを追加してください。

// src/members/members.service.ts

import { Injectable } from '@nestjs/common';
import { Member } from './member.model';

@Injectable()
export class MembersService {
  private members: Member[] = [];

  deleteMember(id: number): void {
    this.members = this.members.filter((member) => member.id !== id);
  }
}

コードの解説

deleteMember(id: number): void メソッド
指定されたIDのメンバーを削除します。引数には削除したいメンバーのIDが渡ってきます。戻り値は
voidとし、何もレスポンスを返しません。

処理の流れ
1.this.members.filter((member) => member.id !== id)
members配列から、指定された id と一致しないメンバーだけを残します。つまり、指定されたidのメンバーはmembers配列から除外されます。

2.配列の更新:
新しい配列を this.members に再代入します。これにより、指定されたIDのメンバーが除かれたmembers配列がメモリ上に保存されます。

メンバー削除APIのコントローラーを実装

次に、メンバー削除のリクエストを処理するコントローラーメソッドを追加します。

// src/members/members.controller.ts

import { Controller, Delete, Param } from '@nestjs/common';
import { MembersService } from './members.service';

@Controller('members')
export class MembersController {
  constructor(private readonly membersService: MembersService) {}

  @Delete(':id')
  deleteMember(@Param('id') id: number): void {
    this.membersService.deleteMember(id);
  }
}

コードの解説

1.@Delete(‘:id’) デコレーター
このメソッドが HTTPのDELETEリクエスト に対応することを示します。

2.void の戻り値
このメソッドは何も値を返しません。削除操作の結果をクライアントに返す必要がない場合は、戻り値を void とします。もちろんこれまでの実装のように、対象のメンバー情報を返しても問題ありません。

3.サービスへの処理委譲
this.membersService.deleteMember(id)により、取得した id をサービスの deleteMember メソッドに渡して、削除処理を実行します。

Postmanでメンバー削除APIを検証

メンバーを登録

これまで行ってきた通り、メンバーを登録しましょう。今回は、以前登録したTanakaさんとSatoさんを登録しましょう。

キー
id1
nameTanaka
age30
emailtanaka@example.com
キー
id2
nameSato
age28
emailsato@example.com

メンバー更新のリクエストを作成

1.新しいリクエストを作成
● HTTP: DELETE
● URL: http://localhost:3000/members/1

2.リクエストを送信
「送信」ボタンをクリックしてリクエストを送信します。

レスポンスの確認

● ステータスコード: 200 OKが返ってくれば成功です。
● レスポンスボディ: 今回はレスポンスボディは返ってきません。

本当に削除されているかを確認

念のために、問題なく削除されているかを確認してみましょう。
以前作成したメンバー一覧取得APIリクエストしてみましょう。
指定したidのメンバー情報がなければ、成功です。

おわりに

ここまで、本当にお疲れさまでした!実際にNestJSを使ってAPIを実装し、CRUD操作が可能なメンバー管理APIを作成することができました。今回の内容で、NestJSの基本的な使い方や、コントローラーとサービスの連携についてしっかりと理解できたのではないでしょうか。

実際のアプリケーションでは、データベースの導入やエラーハンドリング、認証・認可の実装など、さらなる機能が必要になります。しかし、APIの根本的な部分は今回作成したものと同じです。基礎を理解できたあなたなら、これからの挑戦もきっと乗り越えられるはずです。

NestJSを活用して、より高度なAPI開発にチャレンジしてみてください。

アバターのアイコン

この記事を書いた人

アバターのアイコン

takemoto55