diff --git a/cmd/api/movies.go b/cmd/api/movies.go index cc7fd56..11fb383 100644 --- a/cmd/api/movies.go +++ b/cmd/api/movies.go @@ -42,8 +42,22 @@ func (app *application) createMovieHandler(w http.ResponseWriter, r *http.Reques return } - // Dump the contents of the input struct in a HTTP response. - fmt.Fprintf(w, "%+v\n", input) + // Call the Insert() method on our movies model, passing in a pointer to the validated struct. This will create a record in the database and update the movie struct with the system-generated information + err = app.models.Movies.Insert(movie) + if err != nil { + app.serverErrorResponse(w, r, err) + return + } + + // When sending a HTTP response, we want to include a location header to let the client know which URL they can find the newly-created resource at. We make an empty http.Header map and then use the Set() method to add a new location header, interpolating the system-generated ID for our new movie in the URL. + headers := make(http.Header) + headers.Set("Location", fmt.Sprintf("/v1/movies/%d", movie.ID)) + + // Write a JSON response with a 201 Created status code, the movie data in the response body, and the Location header + err = app.writeJSON(w, http.StatusCreated, envelope{"movie": movie}, headers) + if err != nil { + app.serverErrorResponse(w, r, err) + } } // "GET /v1/movies/:id" diff --git a/internal/data/movies.go b/internal/data/movies.go index fda2ae5..409d685 100644 --- a/internal/data/movies.go +++ b/internal/data/movies.go @@ -2,6 +2,7 @@ package data import ( "database/sql" + "github.com/lib/pq" "time" "greenlight.craftr.fr/internal/validator" @@ -51,7 +52,17 @@ type MovieModel struct { // Insert : Inserting a new record in the movies table func (m MovieModel) Insert(movie *Movie) error { - return nil + // Define the SQL query for inserting a new record in the movies table and returning the system-generated data. + query := ` + INSERT INTO movies (title, year, runtime, genres) + VALUES ($1, $2, $3, $4) + RETURNING id, created_at, version` + + // Create an args slice containing the values for the placeholder parameters from the movie struct. Declaring this slice immediately next to our SQL query helps to make it nice and clear *what values are being used where* in the query + args := []any{movie.Title, movie.Year, movie.Runtime, pq.Array(movie.Genres)} + + // Use the QueryRow() method to execute the SQL query on our connection pool, passing in the args slice as a variadic parameter and scanning the system-generated id, created_at and version values into the movie struct. + return m.DB.QueryRow(query, args...).Scan(&movie.ID, &movie.CreatedAt, &movie.Version) } // Get : Fetching a specific record from the movies table