LoginSignup
3
3

More than 3 years have passed since last update.

Protocol Buffersのメッセージ定義からHTMLのフォームを生成してみる実験

Posted at

はじめに

HTMLでフォームを作るのは技術的には簡単なのですが、何度もやることになると作業の重複が多くなって疲れるかと思います。ここではProtocol Buffersを用いてフォームの表示と処理の自動化を試みてみます。実運用するには足りない点も多々ありますので、一つの実験として読んでみて頂ければと思います。

コードは https://github.com/yt76/pbforms にあるので、cloneして(もしくはcloneしたつもりになって)お読みください。 

Protocol Buffersによるフォームの定義

例えば、名前(string)と年齢(int32)と同意の有無(bool)を取得したいとします。このメッセージを my_form.proto というファイルにあるように次の内容で定義します。

    message MyForm {
       optional string name = 1;
       optional int32 age = 2;
       optional bool agree = 3;
    }

これをコンパイルし、

    $ protoc myform.proto --go_out=forms/

それを使うサーバーをビルドし

    $ go build server/server.go

実行し

    $ ./server
    Serving at 8080

ブラウザでアクセスすると

pbf1.PNG

適当に埋めて

pbf2.PNG

送信を押すと

pbf3.PNG

内容がProtocol Buffersのテキスト形式で表示されます。実際のプログラム上ではこの各フィールドの値をデータベースに詰めることになりそうですが、このテキスト形式もしくはProtocol Buffersのバイナリ形式でそのまま保存したりRPCに投げることでProtocol Buffersの機能を使ったデータ操作をするなんてのも可能かと思います。

実装

実装といっても大したことはしてなくて、Goのリフレクションで各フィールドの名前と型を取り出してそれに応じたHTMLを生成し、POSTのハンドラ内ではフィールドの値を戻すといった感じです。

    // コンストラクタ内
    form := forms.MyForm{}
    sv.writer = pbforms.NewFormWriter(form)
    sv.reader = pbforms.NewFormWrite()


    // GETのハンドラ
    fmt.Fprintf(w, "<html><body>\n")
    // <form method="post" action="/">…</form>が生成される
    sv.writer.Write("/", w)
    fmt.Fprintf(w, "</body></html>\n")

    // POSTのハンドラ
    f := forms.MyForm{}
    // r *http.Requestでformの値からfを埋める
    sv.reader.Parse(r, &f)

最後に

  • すぐに思いつく改善点としては見栄えの改善ですが、適当なCSSのクラスを出力してあとからJavaScriptで外側のHTMLのスタイルに書き換えるという手でなんとかなりそうです。
  • ここではstringとintとboolをHTML formのtextとcheckboxに対応させましたが、その他の要素もProtocol Buffersの様々な機能を使えばそんなに無理せずに対応できる?
  • フォーム上にNameとかAgeとかフィールド名をそのまま出してしまってるので、別途メッセージカタログ(国際化もできればなお良い)的なものが必要ですね。

ネット上には様々なフォームがあって、その中には技術の粋をつくした一品物から何かのコピペで済ましたい安易なものまで色々とありますが、適当なレベルのところまではこの記事で紹介したようなものを多少改善すれば間に合うのではないかなと考えてます。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3