gin 入門(3)
前回は WEB Layer のテストケースを考えました。 今回は CLI について考えます
CLIの要件
あるディレクトリに Markdown 形式のファイルを記述しておき、そのファイルからブログ記事を生成する
仕様
とりあえず第三回では CLI の雛形を作ります。実際に Markdown 形式のファイルから記事を生成する方法は長くなるので次回にします。
本エントリーではこんな感じのインターフェースの CLI ツールと作成して articles テーブルにデータを保存するようにします。
publish <title>
ディレクトリ構成
% mkdir cli
ディレクトリ構成は以下のようになります。
% tree -L 1 . ├── cli ├── server └── shared
※前々回 worker というディクトリを作成したと思いますが忘れてください...
まずはコマンドラインで hello, world
create cli/main.go
package main import ( "fmt" "github.com/mitchellh/cli" "log" "os" ) /** foo サブコマンド **/ type Hello struct{} func (f *Hello) Help() string { return "app hello" } func (f *Hello) Run(args []string) int { fmt.Println("hello,", args) return 0 } func (f *Hello) Synopsis() string { return "Print \"Hello!\"" } func main() { // コマンドの名前とバージョンを指定 c := cli.NewCLI("app", "1.0.0") // サブコマンドの引数を指定 c.Args = os.Args[1:] // サブコマンド文字列 と コマンド実装の対応付け c.Commands = map[string]cli.CommandFactory{ "hello": func() (cli.Command, error) { return &Hello{}, nil }, } // コマンド実行 exitStatus, err := c.Run() if err != nil { log.Println(err) } os.Exit(exitStatus) }
実行
% go run main.go hello world hello, [world]
上記のソースコードはこちらを参考にしました。ありがとうございます。 http://qiita.com/uchiko/items/5e5cda98ecb510671e56
タイトルだけ入力
以下のようなようなインターフェース
% go run main.go publish 'title'
shared ライブラリに記事追加機能を実装
edit shared/db_test.go:
func TestAddArticle(t *testing.T) { dbmap := NewDbMap(dsn) CreateTablesIfNotExists(dbmap) defer dropAndClose(dbmap) AddArticle(dbmap, "Go is awesome") rows, _ := dbmap.Select(Article{}, "SELECT * FROM articles") if len(rows) != 1 { t.Errorf("Expected 1 invoice rows, got %d", len(rows)) } article := rows[0].(*Article) if article.Title != "Go is awesome" { t.Errorf("Expected Go is awesome, got %s", article.Title) } }
edit shared/db.go:
func AddArticle(dbmap *gorp.DbMap, title string) (article *Article, err error) { article = &Article{ Title: title, Created: time.Now().Unix(), } err = dbmap.Insert(article) return }
テスト実行
% go test shared/* -v === RUN TestSomething --- PASS: TestSomething (0.04s) === RUN TestAddArticle --- PASS: TestAddArticle (0.03s) PASS ok command-line-arguments 0.078s
つなげてみる
edit cli/main.go:
var dsn = "root:yourpassword@tcp(127.0.0.1:3306)/gin_tutorial" func (f *Publish) Run(args []string) int { fmt.Println("Publish", args) dbmap := shared.NewDbMap(dsn) shared.CreateTablesIfNotExists(dbmap) article, err := shared.AddArticle(dbmap, args[0]) if err != nil { log.Fatalln("Error: ", err) return 1 } fmt.Println("Created: ", article) return 0 }
実行
% go run cli/main.go publish 'Go is awesome' Publish [Go is awesome] Created: &{1 Go is awesome 1440468516 0}
エラーハンドリングが全くなっていないですがコマンドラインに関してはひとまずこんな感じです。
次回はファイルを読み込んでDBに格納するように改修してみます。