Go言語製のWeb Application Framework - Revel - を触る

#なんとなく

Goに対する熱意が冷めないけどよくわからないので、
どうせならWAFから入って少しずつ学習しよう、と思って調べてみたところ、
Revelというものを見つけた。

http://robfig.github.com/revel/

Play-Frameworkを参考に作られたフレームワークらしい。
どういうもんなのかわからんし、Go言語そんなにしらないし試しにTutorialに書かれてるサンプルのコードスニペットを参考にしながら触ってみよう…

http://robfig.github.com/revel/tutorial/index.html


# Go言語のインストールとか

[Tutorial](http://robfig.github.com/revel/tutorial/index.html)に載ってる内容そのまま...

GOPATHの設定。

```
mkdir ~/gocode
echo 'export GOPATH="$HOME/gocode' >> ~/.zshenv
source ~/.zshenv
```

## homebrew より goをインストール。

```
brew install go
```

go getによりリポジトリからrevelをインストール。

```
go get github.com/robfig/revel
```

コマンドラインツールのビルド。

```
cd ~/gocode
go build -o bin/revel github.com/robfig/revel/cmd
```

$GOPATH/bin以下にコマンドがビルドされているので、PATHを通す。

```
echo 'export PATH=$PATH:$GOPATH/bin' >> ~/.zshenv
source ~/.zshenv
```

終わり。

#Revelを試してみる

試しにrevelコマンドを叩くとするか。

```
revel 
```

![revel実行結果](https://dl.dropbox.com/u/614755/qiita/revel/screen-1.png)

通ってるし大丈夫そう。アプリケーションのスケルトンでも自動生成してみると、、

```
revel new myapp
```

![revel new myapp 実行結果](https://dl.dropbox.com/u/614755/qiita/revel/screen-2.png)

$GOPATH/src/myapp にアプリケーションのスケルトンが作成される。
(これについてはIssueでコマンド実行したところにできないの？というのがあったけど、今のところはしょうがないみたい。環境によってビルド先が異なるなどでGOPATHが変わってしまうわけだし…) -> https://github.com/robfig/revel/issues/57

コマンド実行を行うよう促されたので、叩いてみよう。

```
revel run myapp
```

![revel run myapp 実行結果](https://dl.dropbox.com/u/614755/qiita/revel/screen-3.png)

立ち上がった。

![localhost:9000を表示させた結果](https://dl.dropbox.com/u/614755/qiita/revel/screen-4.png)

#コントローラー(のメソッド)を追加

これだけだと寂しいので、コントローラーを一つ追加してみる。

まずは、$GOPATH/src/myapp/app/controller/app.goの現状。

```go:app.go
package controllers

import "github.com/robfig/revel"

type Application struct {
     *revel.Controller
}

func (c Application) Index() revel.Result {
     return c.Render()
}
```

$GOPATH/src/myapp/conf/routes の現状。

```
# Routes
# This file defines all application routes (Higher priority routes first)
# ~~~~

GET     /                                       Application.Index

# Ignore favicon requests
GET     /favicon.ico                            404

# Map static resources from the /app/public folder to the /public path
GET     /public/{<.+>filepath}              Static.Serve("public")

# Catch all
*       /{controller}/{action}                  {controller}.{action}
```

routesに、1つルーティング条件を追加する。

```
# Routes
# This file defines all application routes (Higher priority routes first)
# ~~~~

GET     /                                       Application.Index
GET     /welcome-to-underground                 Application.WelcomeToUnderGround

# Ignore favicon requests
GET     /favicon.ico                            404

# Map static resources from the /app/public folder to the /public path
GET     /public/{<.+>filepath}              Static.Serve("public")

# Catch all
*       /{controller}/{action}                  {controller}.{action}

```
/welcome-to-undergroundを追加しておく。
対応するcontrollerはApplication.WelcomeToUnderGroundとする。

Application.WelcomeToUnderGroundをapp.goに記述する。

```go:app.go
package controllers

import "github.com/robfig/revel"

type Application struct {
     *revel.Controller
}

func (c Application) Index() revel.Result {
     return c.Render()
}

func (c Application) WelcomeToUnderGround() revel.Result {
  return c.Render()
}
```

c.Render()で、$GOPATH/src/myapp/app/view/Application/WelcomeToUnderGround.htmlを拾いに行こうとするので、
view用のhtmlファイルも用意しとく。

```html:WelcomeToUnderGround.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8"/>
    <title>Welcome to underground</title>
  </head>
  <body>
    <h1>Welcome to underground</h1>
    <p>そっと耳元で囁く。</p>
  </body>
</html>
```

ここまでやったら、revelを再起動させ、再度ブラウザで確認を行う。

![Welcome to underground](https://dl.dropbox.com/u/614755/qiita/revel/screen-5.png)


キテる…

#変化のあるウェブを目指す

変化がないとつまらないから、ボタンを置いてなんか動作するようにしよう。

WelcomeToUnderGround.htmlを以下のように変更する。

```html:WelcomeToUnderGround.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8"/>
    <title>Welcome to underground</title>
  </head>
  <body>
    <h1>Welcome to underground</h1>
    <p>そっと耳元で囁く。</p>
    {{if .flash.success}}
    <p>{{.flash.success}}</p>
    {{end}}
    <form method="POST" action="/no-thank-you">
      <button type="submit">No thank you</button>
    </form>
  </body>
</html>
```

flash? なにこれ？気にしない！
routesについて/no-thank-youに対応するため、ルーティング条件を追加する。

```
# Routes
# This file defines all application routes (Higher priority routes first)
# ~~~~

GET     /                                       Application.Index
GET     /welcome-to-underground                 Application.WelcomeToUnderGround
POST    /no-thank-you                           Application.NoThankYou

# Ignore favicon requests
GET     /favicon.ico                            404

# Map static resources from the /app/public folder to the /public path
GET     /public/{<.+>filepath}              Static.Serve("public")

# Catch all
*       /{controller}/{action}                  {controller}.{action}
```

```go:app.go
package controllers

import "github.com/robfig/revel"

type Application struct {
     *revel.Controller
}

func (c Application) Index() revel.Result {
     return c.Render()
}

func (c Application) WelcomeToUnderGround() revel.Result {
  return c.Render()
}

func (c Application) NoThankYou() revel.Result {
  c.Flash.Success("は？")
  return c.Redirect(Application.WelcomeToUnderGround)
}
```

は？とは何か、というのも気にしない。
revelを再起動させましょう。
/welcome-to-undergroundを叩いてみましょう。

![Welcome to underground](https://dl.dropbox.com/u/614755/qiita/revel/screen-6.png)

ボタンが増えているので、クリックしてみましょう。

![Welcome to underground](https://dl.dropbox.com/u/614755/qiita/revel/screen-7.png)


は？

なにこれ。そう、flashとは、リダイレクトするときにcookieにREVEL_FLASHというキーに対して、
c.Flash.Success(message)を行うと、revel側がクッキーにメッセージを追加してくれる機能なのです。便利。

![REVEL_FLASH](https://dl.dropbox.com/u/614755/qiita/revel/screen-8.png)

# 余計なこと

ただ…僕の今時点の状態だとrevelのサーバー側の実装は詳しくわからないし、性能その他どうなのかわからないのと、ORMについてgorpにしようかなとかがWishlist書かれている状態だし、この先どうかはわからんけどgithub上でスターが800以上ついてるし(2013年3月20日現在)、ある程度支持されてるフレームワークだと思えます。いいんじゃないんですかね。

コントローラーについては分割していくことが大切で、自分で使いやすい形にするには
app.goに全部書くとページ数増えていけば死ぬので[Padrino](http://www.padrinorb.com/)とか他のお気に入りのフレームワークからやりかたをパクって実装すると良いと思います。Validationとかも一応機能としてあるけど、どこまでヘルパーが強力かは使い込んでいない。

...Go言語のGoルーチンについてはなんとなく把握というか他のスレッドに実行を委譲してブロックを避ける、という認識ができてるけど、[チャネル型の使い方](http://golang.jp/2009/11/198)とかは改めて何か他のものか、revelリポジトリの[samples](https://github.com/robfig/revel/tree/master/samples)にある[chat](https://github.com/robfig/revel/tree/master/samples/chat)のソースを見て覚えたほうがよさそうだなと思いました。

要はGo言語学習全然してない。ゼロの状態。

余計でした。