Membuat Fungsi Retrieve Data dari Database

Buka file cmd/api/animeModel.go, lalu ubah isi fungsi Get dengan code dibawah.

Digunakan context untuk mengatur in-progress operation. Lalu buat query string untuk mengambil data anime.

func (m *AnimeModel) Get(id int) (*Anime, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
	defer cancel()

	query := `SELECT id, title, description, year
				FROM anime WHERE id = $1
	`

	row := m.DB.QueryRowContext(ctx, query, id)

	var anime Anime

	err := row.Scan(
		&anime.Id,
		&anime.Title,
		&anime.Desc,
		&anime.Year,
	)

	if err != nil {
		return nil, err
	}
	return &anime, nil
}

Kemudian ubah fungsi getAnime pada file cmd/api/animesHandler.go

func (app *application) getAnime(rw http.ResponseWriter, r *http.Request) {
	params := httprouter.ParamsFromContext(r.Context())

	id, err := strconv.Atoi(params.ByName("id"))
	if err != nil {
		app.logger.Println(errors.New("invalid id"))
		app.errorJSON(rw, err)
		return
	}
	app.logger.Println(id)

	anime, err := app.models.Animes.Get(id)

	err = app.writeJSON(rw, http.StatusOK, anime, "anime")
	if err != nil {
		app.errorJSON(rw, err)
	}
}

Jalankan server dengan perintah go run ./cmd/api/. lalu test untuk api diatas dengan url http://localhost:4000/v1/api/anime/1

Sesuai ekspektasi, api diatas berhasil mengambil data dari database.

Latihan

Sebagai latihan, ubah fungsi Get pada file cmd/api/animeModel.go diatas untuk mendapatkan data genre juga.

Solusi

Pertama, tambahkan dahulu data pada tabel animes_genres, sesuaikan dengan data pada tabel animes dan genres.

Lalu modifikasi fungsi Get pada file cmd/api/animeModel.go dengan menambahkan code dibawah.

	query = `SELECT ag.id, ag.anime_id, ag.genre_id, g.genre_name
			 FROM animes_genres ag
			 LEFT JOIN genres g  ON (g.id = ag.id)
			 WHERE ag.anime_id = $1
	`

	rows, _ := m.DB.QueryContext(ctx, query, id)

	genre := make(map[int]string)
	for rows.Next() {
		var ag animeGenre
		err := rows.Scan(
			&ag.Id,
			&ag.AnimeId,
			&ag.GenreId,
			&ag.Genre.GenreName,
		)
		if err != nil {
			return nil, err
		}
		genre[ag.Id] = ag.Genre.GenreName
	}
	anime.AnimeGenre = genre

Jika kita jalankan web app, sesuai ekspektasi, data genre sudah ditampilkan.

Berikut isi lengkap code file cmd/api/animeHandlers.go

package main

import (
	"errors"
	"net/http"
	"strconv"

	"github.com/julienschmidt/httprouter"
)

func (app *application) getAnime(rw http.ResponseWriter, r *http.Request) {
	params := httprouter.ParamsFromContext(r.Context())

	id, err := strconv.Atoi(params.ByName("id"))
	if err != nil {
		app.logger.Println(errors.New("invalid id"))
		app.errorJSON(rw, err)
		return
	}
	app.logger.Println(id)

	anime, err := app.models.Animes.Get(id)

	err = app.writeJSON(rw, http.StatusOK, anime, "anime")
	if err != nil {
		app.errorJSON(rw, err)
	}
}

func (app *application) getAnimes(rw http.ResponseWriter, r *http.Request) {

}

isi lengkap code file cmd/api/animeModel.go

package models

import (
	"context"
	"database/sql"
	"time"
)

type AnimeModel struct {
	DB *sql.DB
}

func (m *AnimeModel) Get(id int) (*Anime, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
	defer cancel()

	query := `SELECT id, title, description, year
				FROM animes WHERE id = $1
	`

	row := m.DB.QueryRowContext(ctx, query, id)

	var anime Anime

	err := row.Scan(
		&anime.Id,
		&anime.Title,
		&anime.Desc,
		&anime.Year,
	)

	if err != nil {
		return nil, err
	}

	query = `SELECT ag.id, ag.anime_id, ag.genre_id, g.genre_name
			 FROM animes_genres ag
			 LEFT JOIN genres g  ON (g.id = ag.id)
			 WHERE ag.anime_id = $1
	`

	rows, _ := m.DB.QueryContext(ctx, query, id)

	genre := make(map[int]string)
	for rows.Next() {
		var ag animeGenre
		err := rows.Scan(
			&ag.Id,
			&ag.AnimeId,
			&ag.GenreId,
			&ag.Genre.GenreName,
		)
		if err != nil {
			return nil, err
		}
		genre[ag.Id] = ag.Genre.GenreName
	}
	anime.AnimeGenre = genre

	return &anime, nil
}

func (m *AnimeModel) All() ([]*Anime, error) {
	return nil, nil
}

Sharing is caring:

Leave a Comment