Updating internal/data/movies.go to Get a movie from the database. Updating cmd/api/movies.go showMovieHandler method to fetch a movie from a request (using the MovieModel's Get method).

This commit is contained in:
Maxime Delporte
2025-11-07 10:58:58 +01:00
parent 0653a46101
commit 0824a127b9
2 changed files with 49 additions and 16 deletions

View File

@@ -1,11 +1,11 @@
package main
import (
"errors"
"fmt"
"greenlight.craftr.fr/internal/data"
"greenlight.craftr.fr/internal/validator"
"net/http"
"time"
)
// "POST /v1/movies" endpoint.
@@ -70,24 +70,20 @@ func (app *application) showMovieHandler(w http.ResponseWriter, r *http.Request)
return
}
/*
Create a new instance of the Movie struct containing the ID we
extracted from the URL and some dummy data. Also notice that we
deliberately haven't set a value for the Year field.
*/
movie := data.Movie{
ID: id,
CreatedAt: time.Now(),
Title: "Casablanca",
Runtime: 102,
Genres: []string{"drama", "romance", "war"},
Version: 1,
// Call the Get() method to fetch the data for a specific movie. We also need to use the errors.Is() function to check if it returns a data.ErrRecordNotFound error in which case we send a 404 Not Found response to the client.
movie, err := app.models.Movies.Get(id)
if err != nil {
switch {
case errors.Is(err, data.ErrRecordNotFound):
app.notFoundResponse(w, r)
default:
app.serverErrorResponse(w, r, err)
}
return
}
// Encode the struct to JSON and send it as the HTTP response.
err = app.writeJSON(w, http.StatusOK, envelope{"movie": movie}, nil)
if err != nil {
// Use the new serverErrorResponse() helper
app.serverErrorResponse(w, r, err)
}
}

View File

@@ -2,6 +2,7 @@ package data
import (
"database/sql"
"errors"
"github.com/lib/pq"
"time"
@@ -67,7 +68,43 @@ func (m MovieModel) Insert(movie *Movie) error {
// Get : Fetching a specific record from the movies table
func (m MovieModel) Get(id int64) (*Movie, error) {
return nil, nil
// The PostgreSQL bigserial type that we're using for the movie ID starts auto-incrementing at 1 by default, so we know that no movies will have ID values less than that. To avoid making an unnecessary database call, we take a shortcut and return an ErrRecordNotFound error straight away.
if id < 1 {
return nil, ErrRecordNotFound
}
// Define the SQL query for retrieving the movie data.
query := `
SELECT id, created_at, title, year, runtime, genres, version
FROM movies
WHERE id = $1`
// Declare a Movie struct to hold the data returned by the query
var movie Movie
// Execute the query using the QueryRow() method, passing in the provided id value as a placeholder parameter, and scan the response data into the fields of the Movie struct. Importantly, notice that we need to convert the scan target for the genres column using the pq.Array() adapter function again.
err := m.DB.QueryRow(query, id).Scan(
&movie.ID,
&movie.CreatedAt,
&movie.Title,
&movie.Year,
&movie.Runtime,
pq.Array(&movie.Genres),
&movie.Version,
)
// Handle any errors. If there was no matching movie found. Scan() will return a sql.ErrNoRows error. We check for this and return our custom ErrRecordNotFound error instead.
if err != nil {
switch {
case errors.Is(err, sql.ErrNoRows):
return nil, ErrRecordNotFound
default:
return nil, err
}
}
// Otherwise, return a pointer to the Movie struct.
return &movie, nil
}
// Update : Updating a specific record in the movies table