SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Scala+Liftによる実践Webアプリケーション開発

Scala+LiftフレームワークのView/Template

Scala+Liftによる実践Webアプリケーション開発(2)

  • X ポスト
  • このエントリーをはてなブックマークに追加

テンプレートをメニューに登録する

 最後に、作成したテンプレートをメニューに登録します。「src/main/scala/bootstrap/liftweb/Boot.scala」を編集します。

 Boot.scalaは、Liftにおけるすべての設定を行うためのクラスです。mavenコマンドでLiftプロジェクトを生成すると、既にDBの設定や文字コードをUTF-8に変更する設定があらかじめ定義されています。

 ここでは、作成したtwit.htmlを登録します。メニューの登録を行うには、LiftRules.setSiteMap関数に、SiteMapオブジェクトを渡します。SiteMapオブジェクトは、Menu型のListを引数に取りますので、リスト8のようにtwit.htmlを登録します。

[リスト8]show関数
class Boot {
  def boot {
    ...

    // entriesはList[Menu]型
    // Menu( Loc( "システムで一意な名称",
    //            "テンプレートへの相対パス",
    //            "メニュー表示用文字列) )
    // の形でメニューを追加する
    val entries = Menu(Loc("Home", List("index"), "Home")) ::
    Menu(Loc("Twit", List("twit"), "ついったーのようなもの")) :: 
      User.sitemap

    // LiftRules.setSitemapに上で作成したList[Menu]型の
    // オブジェクトを渡して登録する
    LiftRules.setSiteMap(SiteMap(entries:_*))

    ...
  }
}

 メニューの登録は、Menu( Loc( "システムで一意な名称",List("テンプレートへの相対パス"),"メニュー表示用文字列) )の形式でMenuオブジェクトを生成して、List[Menu]型の変数entriesに追加しておきます。このentriesを引数にSiteMapを生成して、LiftRulesに登録しています。

動作確認

 プロジェクトディレクトに移動し、「mvn jetty:run」コマンドで開発サーバーを起動します。サーバー起動後に、http://localhost:8080/にアクセスすると、追加されたメニューが表示されていることが確認できるでしょう。

図3:追加されたメニュー
図3:追加されたメニュー

 追加されたメニューをクリックすると、次のような画面が表示され、テキストエリアに入力して[投稿する]ボタンを押すたびに、下の部分に入力した文字列が追加されていくのが確認できるでしょう。

図4:入力フォームと結果出力
図4:入力フォームと結果出力

Function Mappingについて

 従来のMVC型のWebアプリケーションフレームワークと異なり、Liftではボタンのクリックやフォームの送信など、ブラウザ上のイベントを直接scalaで書かれた関数に実行させることができます。この機能を、Function Mappingと言います。

[リスト9]Function Mappingの例
bind("twit", xhtml,
  "name" -> username,
  "status" -> textarea( "", m => message(Full(m)),
    "cols" -> "40", "rows" -> "3"),
  "submit" -> submit( "投稿する",
    () => { Twit.add( message )  })  *1
)

 上記のリスト9は、先ほどのTwit.post関数の一部ですが、SHtmlオブジェクトのtextareta関数やsubmit関数の第2引数で渡している(String) => Any型や() => Any型の関数オブジェクトを渡しています。

 ブラウザでボタンを押してフォームをサブミットすると、サーバー側でこれらの関数が実行されているように見えます。実際にそのとおりなのですが、この動作は従来のMVC型のフレームワークになれている方には、不思議に思えるかもしれません。

 実は、この動作はFunction Mappingという機能で実現されています。

 Liftでは、テンプレートをレンダリングする過程で、任意のHTML要素のイベントに関数オブジェクトを割り当てることができます。上記の例ですと、submitボタンが押されてフォームが送信された場合に、*1で無名関数としてテンプレートを生成したときに作成された() => { Twit.add( message ) }が実行されます。

 この動作を図にすると、次のような関係になります。

図5:Function Mappingの動作
図5:Function Mappingの動作

 Liftでは、SHtml#Submit関数などで渡された関数オブジェクトは、AFuncHolderクラスのサブクラスに変換されて、セッション上に保持されます。セッションに登録する際に、関数オブジェクトごとにユニークなトークンを生成しておいて、ブラウザ上の要素に埋め込みます。先ほどのフォーム画面として生成されたHTMLソースを見てみると、textarea要素やsubmit要素のname属性に、name="F931561949122WAG"のようなトークンが設定されているのが確認できると思います。このトークンはLiftが生成して関数オブジェクトと関連づけているのです。

 以下のリスト10は、リスト9のSnippetが生成したHTMLです。textareaタグやsubmitタグに、name="F765221706401EBZ"のようなトークンが設定されているのが分かると思います。このトークンを含めたHttpリクエストを送信すると、Liftがトークンに対応する関数オブジェクトを呼び出すことで、あたかもボタンを押したときに設定した関数が実行されているように見えるのです。

[リスト10]Function Mappingの例
<form method="post" action="/twit">
  <h2>こんにちわ!Guestさん!</h2>
  <h2>いま何してる?</h2>

  <ul class="status">
    <li><textarea cols="40" name="F765221706401EBZ" rows="3"></textarea></li>
    <li><input name="F765221706402ZPT" type="submit" value="投稿する" /></li>
  </ul>
</form>

 Function Mappingを利用することで、Liftではテンプレートのレンダリングとイベント処理を明確に分離させることができるようになっています。Function Mappingは、通常のHttpリクエストのほかに、AjaxやCommetと組み合わせることで、ブラウザ上のイベントとサーバ上の処理をシームレスに結合させることができるのです。

まとめ

 今回は、LiftのView層について、最も基本的な内容を解説しました。実は、このほかにもLiftが提供する機能として、ajax/cometのサポートや、画像などのバイナリデータの作成方法、RestFulなURLへのマッピングなどさまざまなものがあります。可能であれば、本連載で必要に応じて解説していきたいと思います。

 今回は作成したTwitterのクローンアプリケーションは、投稿されたメッセージがメモリ上に保持されていたり、認証されていなかったり、スレッドセーフでなかったりとさまざまな問題を持っています。この連載を通して、Liftの機能を利用しながらアプリケーションをカスタマイズしていきます。

 次回は、Liftのモデルを利用して、このアプリケーションがデータベースを利用するようにカスタマイズしながら、Liftのモデルについて解説する予定です。

参考資料

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Scala+Liftによる実践Webアプリケーション開発連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 尾崎 智仁(オザキ トモヒト)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/4512 2009/11/16 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング