Top Banner
LiftLive Coding!
36

20081115 Scala勉強会東京#2

Jul 11, 2015

Download

Technology

Tomohito Ozaki
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: 20081115 Scala勉強会東京#2

Liftで Live Coding!

Page 2: 20081115 Scala勉強会東京#2

自己紹介

•  尾崎 智仁 •  ID:yuroyoro •  フリーエンジニア •  Javaとか

Page 3: 20081115 Scala勉強会東京#2

Blog

Page 4: 20081115 Scala勉強会東京#2

今日の内容

1. Liftの紹介 2. Tropyを作ってみよう! 3. Liftって実際どう?

Page 5: 20081115 Scala勉強会東京#2

Liftの 紹介

Page 6: 20081115 Scala勉強会東京#2

Liftの特徴 その1 • ScalaのフルスタックWebフレームワーク

• 最近のフレームワークのいいとこ取り

• Scalaの関数型言語や型推論に加え、既存のjava資産が利用できる。

Page 7: 20081115 Scala勉強会東京#2

Liftの特徴 その2

• インストールやサーバの起動はrailsみたいにMavenコマンド一発。

• データベースも最初からついてる(derby)

Page 8: 20081115 Scala勉強会東京#2

Liftの特徴 その3

• Snipetアプローチ

(View First) • コントローラが中心ではなく、Viewを中心としたアーキテクチャ

• テンプレートはXHTML。独自の名前空間のXMLタグとSnippetを結合

• Wicketのようなコンポーネントが可能に

Page 9: 20081115 Scala勉強会東京#2

Liftの特徴 その4

• ActiveRecordみたいなモデル

+ DjangoのAdmin • モデルとデータベースのマッピングはCoCで簡単に記述

• 簡単にCRUDフォームを作成

Page 10: 20081115 Scala勉強会東京#2

Liftの特徴 その5

• Ajaxサポート • JQuery同梱。

• Ajaxによる呼び出しはajaxCallメソッドでシンプルに実現

• サーバサイドから簡単にJavascriptを実行。

Page 11: 20081115 Scala勉強会東京#2

Liftの特徴 その6

• Commetを簡単・スケーラビリティに

• 設定はCocとScalaコード。XMLなし。

• SiteMapやACLを最初から組み込んである。

• アプリケーションのテンプレートを使えばユーザ管理、サインアップなどが組み込まれた状態で開発できる。

Page 12: 20081115 Scala勉強会東京#2

Liftのアーキテクチャ

Model

LiftFilter

LiftServlet

Boot

LiftRule

LiftSession

RequestState

Snippet

HTML Template

Requestを受けるfilter

URLのDispatchなどのルール

DBなどの動作環境の設定情報

Reqeustの種類(Commet,Ajax)による振り分け

Sessionを扱うRequestの処理。

RequestとResponseの情報。

XHTMLでのテンプレート

Viewへの出力やModelの操作など

KeyedMapper

KeyedMetaMapper ORMでのtrait

CRUD関連処理を 継承

フォームの入力値 などを参照

Modelの操作

XHTMLタグでSnippetを 埋め込む

URLなどからTemplateを検索

URLによる 振り分け

Page 13: 20081115 Scala勉強会東京#2

Tropyを 作ってみよう!

Page 14: 20081115 Scala勉強会東京#2

Tropyってなに?

•  Tropy (とろぴぃ)

•  結城浩さんが作った

•  Web0.5 •  Wikiのように誰でも追加・更新

•  ページの一覧や検索はなし

•  ページ移動はランダムのみ

Page 15: 20081115 Scala勉強会東京#2

Tropyってなに?

ランダムで移動

誰でも追加・編集

Page 16: 20081115 Scala勉強会東京#2

では、やってみよう!

Page 17: 20081115 Scala勉強会東京#2

Tropyを作ろう! – プロジェクト作る

Mavenでコマンドうつ

mvn archetype:create -U \

-DarchetypeGroupId=net.liftweb \

-DarchetypeArtifactId=lift-archetype-basic \

-DarchetypeVersion=0.9 \

-DremoteRepositories=http://scala-tools.org/repo-releases \

-DgroupId=com.yuroyoro.liftropy \

-DartifactId=liftropy

Page 18: 20081115 Scala勉強会東京#2

Tropyを作ろう! – Jettyを起動

Mavenでコマンドうつ

mvn Jetty:run

→ Jettyが立ち上がり

Page 19: 20081115 Scala勉強会東京#2

Tropyを作ろう! – Eclipseへ

Mavenでコマンドうつ

mvn eclipse:eclpse

→ Eclipseのプロジェクトに変換

mvn compile

→ コンパイル

Page 20: 20081115 Scala勉強会東京#2

Tropyを作ろう! – Eclipseへ

Eclpseにインポート

起動構成

-RunWebAppを

メインクラス

Page 21: 20081115 Scala勉強会東京#2

Tropyを作ろう! – Modelを作る

一件分のEntryのModel

package com.yuroyoro.liftropy.model

import net.liftweb.mapper._

object TropyEntry extends TropyEntry with KeyedMetaMapper[Long,TropyEntry]{ }

class TropyEntry extends KeyedMapper[Long ,TropyEntry]{

def getSingleton = TropyEntry def primaryKeyField = tropyId

object tropyId extends MappedLongIndex(this)

object entry extends MappedTextarea(this, 8192) { override def textareaRows = 10 override def textareaCols = 50 }

}

src/main/scala/com/yuroyoro/liftropy/model/TropyEntry.scala

Page 22: 20081115 Scala勉強会東京#2

Tropyを作ろう! – Createテンプレートを作る

Createページのテンプレート

<lift:surround with="default" at="content"> <p>Create</p>

<lift:snippet type="TropySnippet:create" form="POST"/> <hr/> <ul> <li><a href="/">Random</a></li> </ul>

</lift:surround>

src/main/webapp/create.html

Page 23: 20081115 Scala勉強会東京#2

Tropyを作ろう! – Snippet.createを作る

Createページを出力するSnippet

package com.yuroyoro.liftropy.snippet

import scala.xml.{NodeSeq,Text,Group} import scala.Math._

import net.liftweb.http._ import net.liftweb.http.S._ import net.liftweb.util._ import com.yuroyoro.liftropy.model.TropyEntry

class TropySnippet { private object selectedEntry extends RequestVar[Can[TropyEntry]](Empty)

def create(xhtml:Group) :NodeSeq = { <center> <table> {selectedEntry.is.openOr( new TropyEntry).toForm( Empty , saveEntry _ )} </table> <ul> <li><a href="/">Cancel</a></li> <li><input type="submit" value="Create"/></li> </ul> </center> }

def saveEntry( entry:TropyEntry) = entry.validate match { case Nil => entry.save ; redirectTo("/show/" + entry.tropyId) case x => error(x);selectedEntry(Full(entry)) }

}

src/main/scala/com/yuroyoro/liftropy/snippet/TropySnippet.scala

Page 24: 20081115 Scala勉強会東京#2

Tropyを作ろう! – Boot.scalaを修正 Boot.scalaにModelのMigrateと CreateページのPathを登録する

class Boot { def boot { if (!DB.jndiJdbcConnAvailable_?)     DB.defineConnectionManager(DefaultConnectionIdentifier, DBVendor) // where to search snippet LiftRules.addToPackages("com.yuroyoro.liftropy")

Schemifier.schemify(true, Log.infoF _, TropyEntry)

// Build SiteMap val entries = Menu(Loc("Random", "/", "Random")) :: Menu(Loc("create","/create","create")) ::Nil LiftRules.setSiteMap(SiteMap(entries:_*))

} }

src/main/scala/bootstrap/liftweb/Boot.scala

Page 25: 20081115 Scala勉強会東京#2

Tropyを作ろう! – showテンプレートを作る

showページのテンプレート

<lift:surround with="default" at="content"> <p><lift:TropySnippet.show /></p> <hr/> <ul> <li><a href="/create">Create</a></li> <li><lift:TropySnippet.editLink /></li> <li><a href="/">Random</a></li> </ul> </lift:surround>

src/main/webapp/show.html

Page 26: 20081115 Scala勉強会東京#2

Tropyを作ろう! – Snippet.showを作る

showページを出力するSnippet

def show(xhtml:Group) :NodeSeq = S.param("tropyId") match { case Empty => getRandomTropyId match{ case 0 => redirectTo("/create") case tropyId => redirectTo("/show/" + tropyId) } case tropyId => TropyEntry.findByKey( tropyId.open_!.toLong) match{ case Empty => redirectTo("/") case entry => selectedEntry(entry); <p>{entry.open_!.entry}</p> } }

def getRandomTropyId : Long ={ val rand = new Random() TropyEntry.count match { case 0 => 0 case x => (abs(rand.nextLong) % x) + 1 } }

def editLink(xhtml:Group) :NodeSeq = <a href={"/edit/" + selectedEntry.open_!.tropyId}>Edit</a>

src/main/scala/com/yuroyoro/liftropy/snippet/TropySnippet.scala

Page 27: 20081115 Scala勉強会東京#2

Tropyを作ろう! – Boot.scalaを修正 Boot.scalaにModelのMigrateと ShowページのPathを登録する

val entries = Menu(Loc("Random", "/", "Random")) :: Menu(Loc("create","/create","create")) :: Menu(Loc("edit", "/edit", "edit")) :: Menu(Loc("show", "/show", "show")) :: Nil

src/main/scala/bootstrap/liftweb/Boot.scala

/show/<tropyId>のようなURLで、 <tropyId>をパラメータとして扱う LiftRules.addRewriteBefore { case RewriteRequest(ParsePath( “index"::Nil, _,_), _, _) => RewriteResponse("show"::Nil) case RewriteRequest(ParsePath( "show"::tropyId :: _ , _ ,_ ), _, _) => RewriteResponse("show"::Nil , Map("tropyId" -> tropyId)) case RewriteRequest(ParsePath( "edit"::tropyId :: _ , _ ,_ ), _, _) => RewriteResponse("edit"::Nil , Map("tropyId" -> tropyId)) }

Page 28: 20081115 Scala勉強会東京#2

Tropyを作ろう! – editテンプレートを作る

editページのテンプレート

<lift:surround with="default" at="content"> <p>Edit</p>

<lift:snippet type="TropySnippet:edit" form="POST"/> <hr/> <ul> <li><a href="/create">Create</a></li> <li><a href="/">Random</a></li> </ul>

</lift:surround>

src/main/webapp/edit.html

Page 29: 20081115 Scala勉強会東京#2

Tropyを作ろう! – Snippet.editを作る

editページを出力するSnippet

def edit(xhtml: Group): NodeSeq = S.param("tropyId") match { case Empty => getRandomTropyId match{ case 0 => redirectTo("/create") case tropyId => redirectTo("/show/" + tropyId) } case tropyId => TropyEntry.findByKey( tropyId.open_!.toLong) match{ case Empty => redirectTo("/create") case entry => { selectedEntry(entry); <center> <table> {entry.open_!.toForm(Empty, saveEntry _) } </table> <ul> <li><a href={"/show/" + selectedEntry.open_!.tropyId}>Cancel</a></li> <li><input type="submit" value="Edit"/></li> </ul> </center> } } }

src/main/scala/com/yuroyoro/liftropy/snippet/TropySnippet.scala

Page 30: 20081115 Scala勉強会東京#2

Tropyを作ろう! – Template修正

Templateファイルを修正

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:lift="http://liftweb.net/">

<head>

<meta http-equiv="content-type" content="text/html; charset=UTF-8" />

<meta name="description" content="" />

<meta name="keywords" content="" />

<link rel="stylesheet" href="/liftropy.css" type="text/css" media="all" />

<title>Liftropy</title>

<script id="jquery" src="/classpath/jquery.js" type="text/javascript"></script>

</head>

<body>

<h1>Liftropy</h1>

<hr/>

<lift:msgs/>

<lift:bind name="content" />

</body>

</html>

src/main/webapp/templates-hidden/default.html

Page 31: 20081115 Scala勉強会東京#2

Tropyを作ろう! – 完成!

Page 32: 20081115 Scala勉強会東京#2

Liftって 実際どう?

Page 33: 20081115 Scala勉強会東京#2

実際にやってみて – よかったさがし •  Scalaのパウアはすばらしい

(ファーストクラス関数、型推論、パターンマッチ)

•  XMLリテラルはよい

•  ORMよく出来ている(今後に期待)

•  Jettyあげっぱなしでサクサク開発

•  MLが活発(追いきれません…)

Page 34: 20081115 Scala勉強会東京#2

実際にやってみて – disるよ •  ドキュメント不足(ソース嫁)

•  APIとか直感的じゃない

•  Snippetアプローチは正直設計やりにくい

•  コードにHTMLが混ざる

•  Model.toFormが<td>吐くとかねーよ

•  Scala 2.7.2に未対応(!?)

Page 35: 20081115 Scala勉強会東京#2

まとめ

•  実案件への採用は時期尚早

•  ScalaとWebアプリケーションの相性Good!

•  WebFlavor期待age

Page 36: 20081115 Scala勉強会東京#2

ご清聴 ありがとう ございました