【#47 エンジニア転職学習】GinTutorialのWebApp改造　キーワード検索機能追加

# はじめに
富山県に住んでいるChikaといいます。
毎日投稿を目標に、バックエンドエンジニア転職に向けた学習内容をアウトプットします。

GoのフレームワークであるGinを中心に、
webアプリ開発学習をしていきます。

バックエンドエンジニアになるまでの学習内容は以前投稿した以下の記事を基にしています。


https://qiita.com/Chika110/items/ef54dddd565a0193ef44

# 本日の学習内容
GinのTutorialで作成したAPIを改造して、簡素なWebアプリを作成しようと思います

* **GinとGORMを使用したAPIにキーワード検索機能追加　←Topics!!**


# GinとGORMを使用したAPIにキーワード検索機能追加
先日投稿した[コチラの記事](https://qiita.com/Chika110/items/a6decf1f5c49001a6ca3 "")
で作成した簡素なアプリにキーワード検索機能を追加しました。

前回から変更点したファイルのみ記述します。
追加した検索機能でできるようになったことは、以下になります。
* indexページの**検索フォームでArtistに関するワードを入力**
* 検索ワードをもとに`GetAlbumsByKeyword`メソッドで**部分一致するalbumsデータを取得**
* keyalbumlistページで**検索結果の一覧を表示**　
* 一覧からUpdate,Deleteの実行 or indexページに戻る


### app/controllers
~~~webserver.go
package controllers

import (
	"ginapp-albums/app/models"
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"
	"github.com/jinzhu/gorm"
)

type AlbumHandler struct {
	Db *gorm.DB
}

func (h *AlbumHandler) GetAlbums() []models.Album {
	var albums []models.Album

	h.Db.Find(&albums)

	return albums
}

func (h *AlbumHandler) InsertAlbums(c *gin.Context) {
	var albumRequest models.Album

	if err := c.Bind(&albumRequest); err != nil {
		albums := h.GetAlbums()
		c.HTML(http.StatusBadRequest, "index.html", gin.H{"albums": albums, "err": err})
		c.Abort()
	} else {
		title, _ := c.GetPostForm("title")
		artist, _ := c.GetPostForm("artist")
		price, _ := c.GetPostForm("price")
		floatprice, _ := strconv.ParseFloat(price, 64)

		h.Db.Create(&models.Album{Title: title, Artist: artist, Price: floatprice})

		c.Redirect(http.StatusMovedPermanently, "/albums")
	}
}

func (h *AlbumHandler) GetAlbumByID(c *gin.Context) {
	id := c.Param("id")
	checkId, err := strconv.Atoi(id)
	if err != nil {
		panic(err)
	}
	album := models.Album{}

	h.Db.First(&album, checkId)

	c.HTML(http.StatusOK, "update.html", gin.H{"album": album})
}

func (h *AlbumHandler) UpdateAlbumByID(c *gin.Context) {
	id := c.Param("id")
	checkId, err := strconv.Atoi(id)
	if err != nil {
		panic(err)
	}
	var album models.Album
	var albumRequest models.Album

	if err := c.Bind(&albumRequest); err != nil {
		albums := h.GetAlbums()
		c.HTML(http.StatusBadRequest, "index.html", gin.H{"albums": albums, "err": err})
		c.Abort()
	} else {
		title, _ := c.GetPostForm("title")
		artist, _ := c.GetPostForm("aritst")
		price, _ := c.GetPostForm("price")
		floatprice, _ := strconv.ParseFloat(price, 64)

		h.Db.First(&album, checkId)
		album.Title = title
		album.Artist = artist
		album.Price = floatprice
		h.Db.Save(&album)

		c.Redirect(http.StatusMovedPermanently, "/albums")
	}
}

func (h *AlbumHandler) DeleteAlbumByID(c *gin.Context) {
	id := c.Param("id")
	checkId, err := strconv.Atoi(id)
	if err != nil {
		panic(err)
	}
	var album models.Album

	h.Db.First(&album, checkId)
	h.Db.Delete(&album)

	c.Redirect(http.StatusMovedPermanently, "/albums")
}

func (h *AlbumHandler) GetAlbumsByKeyword(c *gin.Context) {
	keyword, _ := c.GetPostForm("keyword")
	var albums []models.Album

	h.Db.Where("artist Like ?", "%"+keyword+"%").Find(&albums)
	c.HTML(http.StatusOK, "keyalbumlist.html", gin.H{"albums": albums})
}
~~~
~~~route.go
package controllers

import (
	"net/http"
	"time"

	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
	"github.com/jinzhu/gorm"
)

func NewRoutes(dbConn *gorm.DB) {
	albumHandler := AlbumHandler{
		Db: dbConn,
	}
	router := gin.Default()

	router.Use(cors.New(cors.Config{
		AllowOrigins:     []string{"*"},
		AllowMethods:     []string{"PUT", "PATCH", "DELETE", "POST", "GET"},
		AllowHeaders:     []string{"Origin"},
		ExposeHeaders:    []string{"Content-Length"},
		AllowCredentials: true,
		AllowOriginFunc: func(origin string) bool {
			return origin == "*"
		},
		MaxAge: 12 * time.Hour,
	}))

	router.LoadHTMLGlob("app/views/*.html")
	router.GET("/albums", func(c *gin.Context) {
		albums := albumHandler.GetAlbums()
		c.HTML(http.StatusOK, "index.html", gin.H{"albums": albums})
	})
	router.GET("/albums/:id", albumHandler.GetAlbumByID)
	router.POST("/albums/new", albumHandler.InsertAlbums)
	router.POST("/albums/update/:id", albumHandler.UpdateAlbumByID)
	router.POST("/albums/delete/:id", albumHandler.DeleteAlbumByID)
	router.POST("/albums/search", albumHandler.GetAlbumsByKeyword)

	router.Run("localhost:8080")
}
~~~
### app/views
~~~index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>AlbumsList</title>
</head>
<body>
    <h1><a href="/albums">AlbumListApp</a></h1>
    <h2>Add Album</h2>
    <form method="POST" action="/albums/new">
        <p>Title <input type="text" name="title" value="{{.album.Title}}" size="30" placeholder="Input Title"></p>
        <p>Artist <input type="text" name="artist" value="{{.album.Artist}}" size="30" placeholder="Input Artist"></p>
        <p>Price <input type="text" name="price" value="{{.album.Price}}" size="30" placeholder="Input Price"></p>
        <p><input type="submit" value="Send"></p>
    </form>

    <h2>ArtistName Search</h2>
    <form action="/albums/search" method="POST">
        <p>ArtistName <input type="text" name="keyword" size="30" placeholder="Input ArtistName"></p>
        <p><input type="submit" value="Search"></p>
    </form>

    <ul>
        {{ range .albums }}
            <li>ID:{{ .ID }} Title:{{ .Title }} Artist:{{ .Artist }} Price:{{ .Price }}
                <label><a href="/albums/{{.ID}}">UPDATE</a></label>
                <label><form action="/albums/delete/{{.ID}}" method="POST"><input type="submit" value="DELETE"></form></label>
            </li>
        {{end}}
    </ul>
</body>
</html>
~~~
~~~keyalbumlist.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>AlbumsList</title>
</head>
<body>
    <h1><a href="/albums">AlbumListApp</a></h1>
   
    <ul>
        {{ range .albums }}
            <li>ID:{{ .ID }} Title:{{ .Title }} Artist:{{ .Artist }} Price:{{ .Price }}
                <label><a href="/albums/{{.ID}}">UPDATE</a></label>
                <label><form action="/albums/delete/{{.ID}}" method="POST"><input type="submit" value="DELETE"></form></label>
            </li>
        {{end}}
    </ul>

    <a href="/albums">Return</a>
</body>
</html>
~~~

##### 使用している教材はこちら↓


https://go.dev/doc/tutorial/web-service-gin


# おわりに
最後までお読みいただきありがとうございました。
アドバイス・応援コメント等いただけますと幸いです。