Posted at

RevelのTutorialに挑戦してみる

More than 3 years have passed since last update.

http://revel.github.io/tutorial/index.html

前回、GolangのWebFramework、Revelの概要を理解したので、今度はチュートリアルに挑戦していきます。なお環境はcloud9です。プロジェクトタイプ:カスタムでGoが使えますが、始めからあるdemo-projectでも問題ありません。


Introduction

Getting Startedを通してとてもシンプルなRevelについて学びましょう。

・Getting started:Revelの入手と起動

・Creating a new Revel app:スケルトンプロジェクトの作成

・The request flow:別手法でのリクエストハンドリング

・Implementing the Hello World app:Hallo World アプリケーションの作成


Getting started

http://revel.github.io/tutorial/gettingstarted.html


Install Go

Revelを使用するにはGoのインストールが必要です。

今回はCloud9を使用するので割愛します。


Set up your GOPATH

インストールでGOPATHを設定しなかった場合、作成が必要です。GOPATHはコードのトップディレクトリになります。なおCloud9ではデフォルトが'~/workspace'になっています。

1.ディレクトリを作成します。

~/workspace (master) $ mkdir gocode

2.GOPATHを設定します。

export GOPATH=~/workspace/gocode

3.設定を保存します。

echo export GOPATH=$GOPATH >> ~/.bashrc


Install git and hg

ライブラリを入手する'go get'を利用するにはGitとMercurialが必要です。Cloud9には既に入っているため割愛します。


Get the Revel framework

Revelを入手するには以下のコマンドを実行します。

go get github.com/revel/revel

このコマンドは$GOPATH/src/github.com/revel/revel/にリポジトリをコピーし、さらにその依存関係を解決します。なお成功した場合、コマンドライン上には何も出力されません。


Get and Build the Revel command line tool

Revelアプリケーションをビルド・実行するにはコマンドラインツールが必要です。以下のコマンドで入手します。こちらも同様にコマンドライン上には何も出力されません。

go get github.com/revel/cmd/revel

$GOPATH/binにrevelコマンドがインストールされましたのでパスを通します。

~/workspace/gocode (master) $ export PATH="$PATH:$GOPATH/bin"

~/workspace/gocode (master) $ revel
~
~ revel! http://revel.github.io
~
usage: revel command [arguments]

The commands are:

new create a skeleton Revel application
run run a Revel application
build build a Revel application (e.g. for deployment)
package package a Revel application (e.g. for deployment)
clean clean a Revel application's temp files
test run all tests from the command-line

Use "revel help [command]" for more information.
~/workspace/gocode (master) $


Creating a new Revel application

http://revel.github.io/tutorial/createapp.html

revelコマンドrevel new myappを実行しアプリケーションを作成します。

~/workspace/gocode (master) $ revel new myapp

~
~ revel! http://revel.github.io
~
Your application is ready:
/home/ubuntu/workspace/gocode/src/myapp

You can run it with:
revel run myapp
~/workspace/gocode (master) $

Cloud9の場合、アドレスとポートを変更する必要があります。


src/myapp/conf/app.conf

# The IP address on which to listen.

http.addr = 0.0.0.0

# The port on which to listen.
http.port = 8080


revel run myappで作成したアプリケーションを起動します。

~/workspace/gocode (master) $ revel run myapp

~
~ revel! http://revel.github.io
~
INFO 2015/04/23 01:23:12 revel.go:329: Loaded module static
INFO 2015/04/23 01:23:12 revel.go:329: Loaded module testrunner
INFO 2015/04/23 01:23:12 revel.go:206: Initialized Revel v0.12.0 (2015-03-25) for >= go1.3
INFO 2015/04/23 01:23:12 run.go:57: Running myapp (myapp) in dev mode
INFO 2015/04/23 01:23:12 harness.go:165: Listening on 0.0.0.0:8080

ブラウザでアクセスします。

できましたね。


The Request Flow

http://revel.github.io/tutorial/requestflow.html

この項ではRevelがどのようにリクエストを扱いウェルカムページを表示したかを見ていきます。


Routes

まず最初にconf/routesをチェックします。

GET     /     App.Index

これはルートパスにアクセスがあった場合、AppコントローラのIndexメソッドを実行することを意味しています。


Actions

ではAppコントローラを見てみましょう。


src/myapp/app/controllers/app.go

package controllers

import "github.com/revel/revel"

type App struct {
*revel.Controller
}

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


全てのコントローラは*revel.Controllerを組み込んだstructです。revel.Resultを返すエクスポートされたメソッドはアクションとして使用されます。エクスポートかどうかはメソッド名の頭が大文字かどうかで判定されます。

Revelコントローラは一般的なResultを返すための多くのメソッドを提供しています。この例ではテンプレートを使用した200 OKなResultを返します。なお次項で説明しますがc.Render()は対応するテンプレートを自動的に見つけ出します。


Templates

テンプレートはapp/viewsの中にあります。上記の例のようにテンプレートが明示されていない場合、app/views/<contorller>/<action>.htmlが対象となります。この場合だとapp/views/App/Index.htmlです。


src/myapp/app/views/App/Index.html

{{set . "title" "Home"}}

{{template "header.html" .}}

<header class="hero-unit" style="background-color:#A9F16C">
<div class="container">
<div class="row">
<div class="hero-text">
<h1>It works!</h1>
<p></p>
</div>
</div>
</div>
</header>

<div class="container">
<div class="row">
<div class="span6">
{{template "flash.html" .}}
</div>
</div>
</div>

{{template "footer.html" .}}


GoテンプレートとRevelは有用なヘルパを用意しています。settemplateなどがそうです。


Hot-reload

Revelはファイルの変更を監視し再コンパイルしてくれます。確認するためにIt workds!Hello Revelに変えて保存してみましょう。ブラウザを更新すると次のようになるはずです。

Revelは次のファイルを監視してます。


  • app/以下のgoファイル

  • app/views/以下のテンプレート

  • conf/routes

ここでコンパイルエラー時の画面表示を確認してみましょう。app.go の c.Render() を c.Renderx()にして、画面を更新してみましょう。



このようにわかりやすいメッセージが表示されます。

では次にコントローラからテンプレートに値を渡してみましょう。

func (c App) Index() revel.Result {

greeting := "Aloha World"
return c.Render(greeting)
}

テンプレートでその値を使います。

<h1>{{.greeting}}</h1>

画面を更新して確認します。

できましたね。


The 'Hello World' app

http://revel.github.io/tutorial/firstapp.html

ではハローワールドアプリケーションの作成に移りましょう。

flashテンプレートより下に次のフォームを追加します。

<form action="/App/Hello" method="GET">

<input type="text" name="myName" /><br/>
<input type="submit" value="Say hello!" />
</form>

サブミットしてみましょう。エラーになります。

ではアクションとビューを用意しましょう。


app.go

func (c App) Hello(myName string) revel.Result {

return c.Render(myName)
}


app/views/App/Hello.html

{{set . "title" "Home"}}

{{template "header.html" .}}

<h1>Hello {{.myName}}</h1>
<a href="/">Back to form</a>

{{template "footer.html" .}}


ではもう一度サブミットしてみましょう。入力欄にはRevelと入れています。

本文では全く触れてませんが、フォーム送信データとアクションの引数でmyNameがバインディングされています。

ではちょっとしたバリデーションを追加してみましょう。myNameは必須で3文字以上という制限をかけます。


app.go

func (c App) Hello(myName string) revel.Result {

c.Validation.Required(myName).Message("Your name is required!")
c.Validation.MinSize(myName, 3).Message("Your name is not long enough!")

if c.Validation.HasErrors() {
c.Validation.Keep()
c.FlashParams()
return c.Redirect(App.Index)
}

return c.Render(myName)
}


これらのバリデーションエラーはflashテンプレートで表示されます。

現状ですと不正な値を入力した場合、フォームがクリアされていると思います。場合にもよりますが残しておいたほうがいいケースも多々あるでしょう。そのためには次にようにします。


index.html

<form action="/App/Hello" method="GET">

{{with $field := field "myName" .}}
<input type="text" name="{{$field.Name}}" value="{{$field.Flash}}"/><br/>
{{end}}
<input type="submit" value="Say hello!" />
</form>

これで誤ったデータを修正可能になりました。

以上でチュートリアルは終わりとなります。

お疲れ様でした。