はじめに
RevelのBookingという公式サンプルアプリケーションはDBがSqlite。
これをPostgreSQLにしてHerokuにデプロイしようという話。
ひとまず動いたものは下記に置いておいた。
https://github.com/shunsugai/revel-sample-booking-postgres
変更点
まず、Bookingというサンプルアプリを用意しておく。下記のもの。
https://revel.github.io/samples/booking.html
変更点は下記。
- conf/app.confをPostgreSQL用に変える
- gorp.PostgresDialect{}に変える
- プレースホルダを変える
- Userの名前変える
- LIMIT句を修正
1. conf/app.confをPostgreSQL用に変える
log.warn.prefix = "WARN "
log.error.prefix = "ERROR "
-db.import = github.com/mattn/go-sqlite3
-db.driver = sqlite3
-db.spec = :memory:
+db.import = github.com/lib/pq
+db.driver = postgres
+db.spec = ${DATABASE_URL}
build.tags=gorp
2. gorp.PostgresDialect{}に変える
func InitDB() {
db.Init()
- Dbm = &gorp.DbMap{Db: db.Db, Dialect: gorp.SqliteDialect{}}
+ Dbm = &gorp.DbMap{Db: db.Db, Dialect: gorp.PostgresDialect{}}
setColumnSizes := func(t *gorp.TableMap, colSizes map[string]int) {
for col, size := range colSizes {
3. プレースホルダを変える
PostgreSQLはプレースホルダが\$1, \$2という感じなので"?"をこれに変える。
下記はその一例。
var hotels []*models.Hotel
if search == "" {
hotels = loadHotels(c.Txn.Select(models.Hotel{},
- `select * from Hotel limit ?, ?`, (page-1)*size, size))
+ `select * from Hotel limit $1, $2`, (page-1)*size, size))
} else {
search = strings.ToLower(search)
4. Userの名前変える
3まででイケるかと思いきや、デプロイすると下記のようなエラーが出た。
panic: No ColumnMap in table User type User with field userid
下記によるとuserというテーブル名が良くないらしい。
https://groups.google.com/forum/#!topic/revel-framework/fi7q2rT21NU
I found out the reason for my final error: since there is a User model object, gorp creates a "user" (lowercase for unexplained reasons) table in postgres. When you query that table with "select * from user", postgres thinks you are talking about a built-in user object (containing one column, current_user_name).
というわけで下記のように名前を変えてみた。
"regexp"
)
-type User struct {
+type HotelUser struct {
UserId int
Name string
Username, Password string
Userを参照している箇所はすべて置換してください。
5. LIMIT句を修正
4まででイケるかと思いきや、デプロイして/hotelsにアクセスしてもホテル名の一覧が出てこない。
ログを見ると下記のエラーが出ていた。
ERROR 2015/11/07 08:07:07 panic.go:30: pq: LIMIT #,# syntax is not supported
LIMIT句の書き方が違うよと。あまりにも無知。
var hotels []*models.Hotel
if search == "" {
hotels = loadHotels(c.Txn.Select(models.Hotel{},
- `select * from Hotel limit $1, $2`, (page-1)*size, size))
+ `select * from Hotel offset $1 limit $2`, (page-1)*size, size))
} else {
search = strings.ToLower(search)
hotels = loadHotels(c.Txn.Select(models.Hotel{},
`select * from Hotel where lower(Name) like $1 or lower(City) like $2
- limit $3, $4`, "%"+search+"%", "%"+search+"%", (page-1)*size, size))
+ offset $3 limit $4`, "%"+search+"%", "%"+search+"%", (page-1)*size, size))
}
return c.Render(hotels, search, size, page, nextPage)
これでコードの修正は完了。
Herokuにデプロイする。
詳細は下記。
golang - [Go] HerokuにRevelでつくったアプリをデプロイする - Qiita
.godirまで用意したものとして進めます。
まずherokuのインスタンス作成。
$ heroku create -b https://github.com/revel/heroku-buildpack-go-revel.git
次にポスグレのaddon追加
https://elements.heroku.com/addons/heroku-postgresql
$ heroku addons:create heroku-postgresql:hobby-dev
最後にdeploy
$ git push heroku master
終わったらブラウザで確認。
heroku open
いぇーい。
InitDB()呼ばれるたびにレコード増えてくけど気にしない気にしない。
詳しくは下記を見てください。
https://github.com/shunsugai/revel-sample-booking-postgres