Completing CRUD Operations with Controllers, Services, and DTOs
Introduction: Why CRUD Matters for Books and Users
Welcome back! In the previous lesson, you learned how to create new resources in your API using DTOs and validation. Now, we will complete the core features for managing both books and users by implementing all CRUD operations — Create, Read, Update, and Delete. These operations are the foundation of almost every web application, allowing you to add, view, change, and remove data as needed.
CRUD stands for:
- Create – Add new data (via
POST) - Read – Retrieve existing data (
GETone or all) - Update – Modify data (
PATCHorPUT) - Delete – Remove data (
DELETE)
These actions mirror how real apps behave — whether you're building a task manager, social platform, or e-commerce dashboard. In NestJS, each of these actions maps to a method in a controller, which delegates logic to a service, ensuring separation of concerns.
In this lesson, you will see how these operations work together in the Reading Tracker API. By the end, you will understand how to manage both books and users through the API, setting you up for hands-on practice and real-world projects.
Quick Recap: Project Structure and Setup
Before we dive in, let’s quickly remind ourselves how the project is organized. You already have a NestJS app with modules for books and users, each with its own controller, service, and DTOs. The data is stored in a simple in-memory database service.
Here’s a quick summary of the setup:
This structure helps keep your code organized and makes it easy to add new features.
Controllers: Handling Requests for Books and Users
Controllers are responsible for handling incoming HTTP requests and sending responses. Each controller method matches a specific API endpoint and HTTP method.
Let’s look at some examples from the BooksController and UsersController:
Each method does the following:
@Post()handles creating a new book.@Get()returns all books.@Patch(':id')updates a book by its ID.@Delete(':id')removes a book by its ID.
The
@Patch(':id')route is used for partial updates. For example, you might only want to change the book's title without updating the author.
@Param('id', ParseIntPipe)extracts and converts theidfrom the URL.@Body()maps the request body into a typed DTO and applies validation.- The controller passes this sanitized input to the service layer.
The same pattern is used in the UsersController for managing users.
Explanation:
When a request comes in (for example, a POST to /books), the controller method receives the request data, calls the appropriate service method, and returns the result. The @Param and @Body decorators help extract data from the request.
