Lift2.2M1のテンプレート機能

Lift2.2M1での超便利なテンプレート周りの機能追加についてまとめてみました。CSSセレクタを使ったスニペットと、コントローラーベースの開発手法の追加が、衝撃的です。

Lift2.0から2.2M1までのリリースノート
http://liftweb.net/22_m1
http://liftweb.net/21_ga
http://liftweb.net/20_ga

Lift2.0からたくさんの機能追加がありました。
目立つものにはLiftMapperの後継としてLiftRecordを使って各Key-Valueストアをサポートしたことなどが挙げられますが、ここでは主に、テンプレート周りの変更についてまとめておきます。

Lift2.0からScala2.8とsimple-build-toolが正式サポートされたので、Scala2.7とMavenは捨てる方向で。

-------------------------------------------------------

動作確認方法

Lift1.1のころのMavenを使う方法から、sbtプロジェクトテンプレートをダウンロードする方法がメインになりました。

http://liftweb.net/download
「DOWNLOAD and run using SBT」からLift2.2M1のZipをダウンロード。
解凍すると、lift_basic/lift_blank/lift_mvcがありますが、今回はデータ層は使わないので、lift_blankを使って遊んでみます。

> cd lift_blank
> sbt
sbt> update
sbt> jetty-restart

-------------------------------------------------------

Designer Friendly Templates

LiftWiki:Designer Friendly Templates

従来は、

  <div class="ttl"><lift:mySnippet.title /></div>

  class MySnippet{
    def title(xhtml:NodeSeq) = Text("タイトル")
  }

テンプレート上のliftタグにスニペットで編みこんで出力する、という仕様でしたが、XHTMLのclass属性にSnippet名を指定することで、同様の処理ができるようになった。

  <div class="ttl lift:mySnippet.title">xxxxxx</div>

これによって、XHTMLのデザインを全く壊すことなく、スニペットの編みこみができるというもの。
スニペット側は変更する必要はありません。


さらに便利なのはCSSセレクタを利用して、探索したタグに編みこむこともできる。

  <div class="ttl lift:mySnippet.title">
    <span class="title">xxxxxx</span>(<span class="time"/>)
  </div>

  class MySnippet{
    def title(xhtml:NodeSeq) =
      ".title" #> "タイトル" &
      ".time" #> new Date().toString
  }


変わった点をまとめると

テンプレート側:
 <lift:>を始め、面倒なXMLサフィックスがなくなった。
 ブラウザでそのまま表示できるHTMLファイルになった。

Snippet側:
 メソッドの戻り値はnet.liftweb.util.CssBindFuncとなった。
 bindする文字列をTextなどに変換しなくて良い。
 さらに引数は定義しなくて良い。
 Helper.bindメソッドの煩わしさがない!

・・など、Programmer Friendlyな結果になっている。
これはLift2.2に乗り換えるしかなくなった!!というくらいの衝撃です。

CSSセレクタとbindできる型のバリエーションなどは、
LiftWiki:Binding via CSS Selectorsを参照。
-------------------------------------------------------

MVCHelper

Liftは基本的にViewFirstのアーキテクチャですが、StrutsやRailsのようないわゆるMVCで開発したい人もいるでしょう。そんなに「どうしてもMVC使いたい」なら、こんなオプションあるよ。という機能のようです。

LiftWiki:MVC (if_you_really_want_it)

前述のCssBindFunc採用の副産物っぽい感じです。

正直、MVCベースに開発したいなら無理にLiftを使うより、
Play Framework for Scalaなどを使う方が賢い選択とは思いますが、
「この部分だけはMVCで作ったほうがきれいだ!」みたいなケースもあるかもしれないです。

やってみよう。
まずテンプレートからSnippetの指定を取り除く。

  <div class="ttl">
    <span class="title">xxxxxx</span>(<span class="time"/>)
  </div>

コントローラーを記述する。

package code.controller

import net.liftweb.http._
import net.liftweb.util._
import Helpers._
import _root_.java.util.Date

object MyController extends MVCHelper {
  serve {

    case "index" :: Nil =>
      ".title" #> "タイトル" &
      ".time" #> new Date().toString

    case "help" :: Nil =>
      for {
        template <-TemplateFinder.findAnyTemplate("index" :: Nil)
      } yield (
        ".title" #> "ヘルプ" &
        ".time" #> new Date().toString
      ).apply(template)
  }
}

こちらのアプローチの方が、条件によるテンプレートの切り替えや使いまわしが簡単にできることがわかる。

コントローラーをBootに登録して実行。

  //SiteMapと競合しないように削除
  //LiftRules.setSiteMap(SiteMap(entries:_*))

  LiftRules.dispatch.append(code.controller.MyController)

コントローラーが肥大化するようなら、複数に分けてLiftRules.dispatch.appendすれば良いし、以下のようにもできるはず。

 trait AController { self:MVCHelper =>
  serve {
   case "a" :: Nil => ...
  }
 }
 trait BController { self:MVCHelper =>
  serve {
   case "b" :: Nil => ...
  }
 }
 object MyController extends MVCHelper with AController with BController

思った以上に楽で、Liftがとたんに普通のフレームワークに見えてきましたっ
----------------------------------------------------

Scalateのサポート

Liftのテンプレートエンジンは、XHTMLとSnippetによる独自のもの(LiftView)ですが、Scalateも利用できるようになりました。

Scalateは、数種類のテンプレートエンジンのセットですが、Liftでは、SSPScamlが利用できるようになってます。いずれもScalaの評価式を直接テンプレートに埋めていくもの。

Mustacheがサポートされないのは残念。Scueryと似たことは前述のDesigner_Friendly_Templatesで実現できます。

LiftViewとScalateの比較記事がありますが、ケースバイケースですね。という結論のようです。

ちょっとしたページ作るのにいちいちSnippetとかやってらんねーという場合は良いと思いますが、JSPに懲りてしまうようなケースでは使わない方がよさそう。と個人的に思います。


使い方
lift_blank/project/build/LiftProject.scalaの
libraryDependenciesに以下を追記

 "net.liftweb" %% "lift-scalate" % liftVersion % "compile->default",

sbt> reload
sbt> update

Boot.scalaに以下を追記。

 import net.liftweb.scalate._
 (new ScalateView).register

あとは、*.scamlや*.sspを開発して配置するだけだと思います。(動作確認はしてません)

サンプルは、以下にあります。
helloscalate


同じカテゴリのエントリ
1.Lift再入門 / 8.javascriptからsubmitできない / 7.Ajax Form / 6.Radio、Checkboxについて / 5.行列型の編集FORM / 4.サーバーサイドバリデーションとサーバサイド関数 / 3.ログインFORM - S.param使ったら負け / 2.Snippetメソッドとして許される型 / sbt0.12.xで依存jar抽出タスク / scala2.10+lift2.5+NetBeans7.2 / Scalaで入門関数プログラミング / reactive-webを試してみました / Lift2.2M1のテンプレート機能 / Scala Compiler Plugin / View Bound/Context Bound / ScalaZa01参加してきました / Akka Frameworkチュートリアルの次 / Akka Frameworkチュートリアルその2 / Akka Frameworkチュートリアル / LiftでJCaptcha / Url Rewrite Filter / sbt-android-plugin / Android SDK for Scala / 祝Lift2.0リリース / Liftの携帯対応まとめ / Scala2.8への移行 / Lift 2.0-scala280-SNAPSHOT/sbt0.7.1 / Scalaお絵かき環境 - Kojo / Lift+Quartzでバッチ / Scala&Liftを採用した理由 / Liftでdate_select系ヘルパーを作る / LiftでAjax / LiftのSubmitかしこい / lift-mapperのpaginateを使う / snippetをspecする / Lift Mapperを拡張する / LiftのDBをMySQLに / Liftプロジェクト環境を整える / Scala本読み比べてみました / NetBeans6.7&scala / じつはScalaはライトな言語 / Scalaバザ~ル / lift1.0所感 / specsを読む / implicit def / ScalaならNetBeansがサイコー / scala勉強会@東北がスタート / それでも俺はLiftをやるってのか / Scala&Liftセットアップ / ブログリニューアル /
コメント

コメントしてください

closed.