Scalate の公式サイトが GH pages に移行
Scala の老舗テンプレートエンジンで私自身 Skinny Framework のコアなコンポーネントとして利用している Scalate のウェブサイト http://scalate.fusesource.org これが閉じることになったらしく GitHub pages に移行しました。今日になってアクセスしてみると http://scalate.fusesource.org はもはやアクセスできなくなっていてました。一定期間リダイレクトするとか・・そういうのないですか。そうですか。
https://github.com/scalate/scalate/pull/60
The box hosting http://scalate.fusesource.org is going to be shutdown very soon (ideally today :-) ). Could someone merge this PR and also grab the gh-pages branch at https://github.com/janstey/scalate/tree/gh-pages so the website will be hosted at http://scalate.github.io/scalate ?
こんな記事もありましたが
Scala 2.11 対応の Scalate 1.7.0 が Scalatra 2.3.0 のタイミングに合わせて @rossabaker さんのリードによりリリースされたものの、公式サイトは放置されていて最新バージョンは 1.6.1 のままでした。organization(Maven でいう groupId)も変わっているというのに...
今回の公式サイト移行をみて、これはいい機会とばかりにウェブサイトを 1.7.0 対応にする Pull Request をして
Update GH page for Scalate 1.7.0 by seratch · Pull Request #61 · scalate/scalate · GitHub
日本のみなさんに :+1: をお願いしたところ
新しいページはここになるそうなんですが、1.7.0 の情報がないので PR しています。:+1: で応援してください。 http://t.co/N8x0AJWBZb https://t.co/VuZZSNndDy #ScalaJP
— Kazuhiro Sera (@seratch_ja) 2014, 10月 1
無事マージされました。ありがとうございます!
merge されました。ありがとうございました! http://t.co/N8x0AJWBZb
— Kazuhiro Sera (@seratch_ja) 2014, 10月 1
ということで Scalate の公式サイトはこちらになりました。
Skinny Framework からのリンクも更新しておきました。
最近は Scala といえば Play で Play といえば Twirl ですが、Scalate もなかなか便利ですよ。ぜひ皆さん使ってみてください。
ScalaMatsuri ふりかえり(今更)
何となく ScalaMatsuri のふりかえりでもしてみようかという気分になりました。自分の中での整理という感じなので、あまり面白みはないかもしれません。
Scala と私
というところで見直してみたけど、私の Scala への関わり方は以下のスライドに全てあらわれているので、その点はもう補足の必要がないですね。私の活動に興味を持っていただいていた方にとっては、やってきたことそのままであることがおわかりいただけるかと思いますが、この機会に明文化できて自分としては一区切りついたというか、すっきりした感はあります。
スライド
もう少し踏み込んだ話
もう少し踏み込んで言うと、もしも Scala 使うようになって前より仕事が楽になったり、楽しくなっていないとしたらそれは明らかに間違っているというか、少なくとも今いるメンバー、やろうとしてることとのミスマッチがあるわけなので「頑張って FP の勉強しなきゃ」「コンパイル早くならないかな」の前に考えるべきことがあるのでは?と思ったりしています。
もっと直球で言えば、何となく他の選択肢を検討することを嫌ってはいけないということです。それを考えてもなお Scala ということだったのかという。そして既に Scala でやっているのならば、その中でどんどんベストプラクティスを見つけていって、それをコミュニティで共有したいですよねという。まだ若いコミュニティですし。
「Scala を使って本番ロンチしました!」という事例が多く出てくることはすばらしいのですが「ぶっちゃけ困ってること結構あるでしょ」「これから持続していく必要があるわけだけど、大丈夫そうですか」というのが私の最近の関心事です。もちろん「うちは万全!」という人たちもいると思うので、そういう人にぜひコミュニティでもっと目立ってもらえるとよいかなと。怖いとか怖くないとかはそろそろいいのでもっと現実の話をしたいですね。
そして、私も微力ながら可能な限りそれを解決することに貢献していきたいと思っていますが、OSS の開発という面では特定の納期に合わせるというものでもないですし、個別の案件としては色々あるというのが実際のところかなと思います。
英語プレゼンの件
英語発表の件でスタッフの方々にお手間をおかけしたことは申し訳なかったですが、長期的には「そんなこともあったね」とふりかえることができるだろうと思っているので、後悔はしていません。ただ、私のトークに満足いただけなかった方に対しては率直に私の力不足を詫びたいと思いますし、発表内容だけでなく運営としても改善点はあっただろうとも思います。
一方で、これはあくまで私個人の意見として言わせていただきますが、コミュニティは誰かが与えるものではなくみんなで育てていきたいと思っていますし、私個人としてはそういう場所こそを大事にしたいということを感じた出来事ではありました。
これからの Scala コミュニティ
Scala が好きな人だけで集まるのも楽しいですが、そもそも今でもオブジェクト指向と関数型の交差点として混沌としている面白さがある界隈です。もし「正直 Scala 自体はそんなに好きじゃないんだけど、Scala に関連したアレが便利すぎるから Scala 界隈に絡んでいる」みたいな人たちが出てきて、もっと多様性のあるコミュニティになったりすると、より一層面白くなるのではないかと思います。Spark とかはその兆しかもしれません。
日本のコミュニティが世界に閉じていないというのも一つの目標ですが、ふとそういう未来も見てみたいと妄想しました。
Scala DB ライブラリ事情(2014/06 版)
最初に調べてから一年経ったので、また GitHub スター数の推移を見てみました*1。というか、こういうの自動化するサービスがあるといい気がしてきたけど。。
DB ライブラリ
順位 | 名前 | 2013/06 | 2013/07 | 2013/08 | 2013/09 | 2013/10 | 2014/06 | 総増減 |
---|---|---|---|---|---|---|---|---|
1 | Slick | 613 | 638 | 658 | 692 | 717 | 922 | +309 |
2 | postgresql-async | 159 | 187 | 213 | 227 | 240 | 421 | +262 |
3 | Squeryl | 322 | 329 | 334 | 338 | 340 | 365 | +43 |
4 | ScalikeJDBC | 112 | 135 | 141 | 150 | 180 | 274 | +162 |
5 | Querulous | 154 | 157 | 158 | 162 | 164 | 170 | +16 |
6 | scala-activerecord | 92 | 101 | 104 | 113 | 130 | 168 | +76 |
7 | Activate | 85 | 94 | 99 | 103 | 112 | 163 | +78 |
8 | sqltyped | 109 | 108 | 110 | 119 | 121 | 162 | +53 |
9 | SORM | 91 | 95 | 97 | 100 | 102 | 127 | +36 |
10 | ScalikeJDBC-Async | - | 14 | 20 | 27 | 28 | 59 | +59 |
11 | Prequel | 35 | 37 | 39 | 41 | 44 | 58 | +23 |
12 | Relate | - | - | - | - | - | 42 | +42 |
13 | DataExpress | 24 | 24 | 27 | 27 | 29 | 37 | +13 |
14 | Scala SQL DSL | 28 | 27 | 27 | 27 | 28 | 28 | 0 |
15 | jdub | - | - | - | - | - | 24 | +24 |
16 | MyBatis Scala | 1 | 3 | 4 | 4 | 7 | 14 | +13 |
17 | ScalaSQL | 12 | 13 | 13 | 13 | 13 | 13 | +1 |
18 | Scweery | 12 | 12 | 12 | 12 | 12 | 11 | -1 |
19 | mirage-scala | 4 | 4 | 4 | 5 | 5 | 7 | +3 |
20 | shirahae-sql | - | - | 2 | 2 | 2 | 2 | +2 |
フレームワークの一部
順位 | 名前 | 2013/06 | 2013/07 | 2013/08 | 2013/09 | 2013/10 | 2014/06 |
---|---|---|---|---|---|---|---|
1 | Anorm | - | - | - | 3697 | 3797 | 4906 |
2 | Lift Mapper | - | - | - | 717 | 722 | 796 |
3 | Spring JDBC Scala | 154 | 168 | 182 | 194 | 212 | 262 |
4 | Skinny ORM | - | - | - | - | 99 | 251 |
5 | Circumflex ORM | 136 | 136 | 137 | 140 | 143 | 155 |
感想など
Slick と postgresql-async のスターがかなり増えていますね。また、手前味噌ですが ScalikeJDBC、Skinny ORM も順調に成長できたといってよいのではないかと思います。
注目すべき点としては Relate というライブラリが出てきてなかなか面白い存在です。Anorm と比較して「パフォーマンス的に生 JDBC と同等」とうたっています。
https://www.lucidchart.com/techblog/2014/06/17/performant-database-access-relate/
提供している Lucid Software というのはデータ分析をビジネスとする会社のようです。元々 Anorm を使っていたものの、かなり大量のデータを扱う必要があって ResultSet からの取り出し部分でのオーバーヘッドが無視できなかったため、独自で開発したとのこと。ここでいうオーバーヘッドは ResultSet からの取り出し部分に限った話なので、通常はそれほど重視する必要はないかなと思いますが、速いのはよいことですね。
また Simple Finance Technology という会社が出している jdub というライブラリを見落としていたようで、こちらを加えました。ただ、この会社が Scala 2.9.2 を使い続けているのか、他のバージョンへのリリースがされておらず、新しい Scala のメジャーバージョンが出る度に issue が登録されている状況のようです。ていうか、なんかビルドが Maven だけど...。
この会社、テストライブラリも自作していたりして、なかなか興味深いです。
https://github.com/SimpleFinance/simplespec
simplespec も Maven でやっているようですが、こちらは 2.11 にもビルドしているようなので jdub は一部の Scala 2.9.2 なレガシープロジェクトだけで使っているということなのかもしれません。
一般的にライブラリの提供元が会社であるということは、半強制的にメンテナンスがチーム体制となるので、継続性という面はプラス要因といえます。それだけでなく、少なくとも何らかの本番環境で使われているということの証明でもあります。最近の OSS では会社をつくるケースが増えている印象もありますが、やはり仕事の一環としてメンテナンスされているというのはよい状況だと思います。
私がやっているようなボランティアベースの開発においても、そのライブラリを使っている会社の開発者を積極的に関係者に巻き込んでいくことで、会社をまたいだ業界内のギルトのようなチーム*2でメンテされる状況をつくることができればいいと思っています。ということで、既に関わってくださっている方々にはとても感謝しております。いつもありがとうございます。
JJUG CCC 2014 Spring で登壇しました #jjug_ccc
JJUG CCC 2014 Spring – R2-4 Skinny Framework で始める Scala
http://www.java-users.jp/?page_id=1048#R2-4
プレゼン資料
感想など
運営の皆様ありがとうございました。懇親会も非常に楽しかったです。
Skinny よかったらぜひ使ってみてください。
Skinny Framework 1.0.0-RC1 をリリース
English?
This is an article for Japanese developers. English article is here:
http://blog.seratch.net/post/77537302500/try-skinny-framework-1-0-0-rc1
Release Candidate 1
Skinny Framework 1.0.0-RC1 をリリースしました。基本的にはこれからは大きな機能追加はせずにバグの修正や API の最終的な確認・改善を行っていきます*1。
これから約 1 ヶ月、いろんな方に試していただいて final を良い形でリリースできればと思っています。
まずチームに感謝
私一人の力ではありません。本業も忙しい中、contribute してくださった @BlackPrincess と @Arakaki の両氏と pull request を下さった全ての方に感謝いたします。
公式ドキュメント
こちらです。全て英語ですが、私が書いているので全部平易な表現で書かれています。
試す
Skinny Framework はすぐに試せます。JDK さえ入っていれば Mac OS X、Linux、Windows を問わず skinny コマンドだけを使って起動するまではとても簡単に試せます。
wget https://github.com/skinny-framework/skinny-framework/releases/download/1.0.0-RC1/skinny-blank-app.zip unzip skinny-blank-app.zip cd skinny-blank-app ./skinny run
scaffold を試すのが理解の近道です。Rails と似た感じで*2、簡単に scaffold を試せます。基本的には動かしながら scaffold しても大丈夫です*3。
./skinny g scaffold:jade members member name:String "nickname:String:varchar(64)" birthday:Option[LocalDate] ./skinny db:migrate ./skinny run
にアクセスすると members テーブルの CRUD 画面が動作していることを確認できます。
テストを実行する
テストも大事ですね。db:migrate を忘れずに。
./skinny db:migrate test ./skinny test
カバレッジ計測も大事ですね。ということで scoverage を使えるようにしていますが
./skinny scoverage:test
Skinny ORM の SkinnyCRUDMapper との相性が悪いようです。これはまだ詳細未調査なのでフィードバックできていないのですが、解決に向けて動いていければと思っています。
war ファイルをつくる
package コマンドを実行するだけです。build の下に生成されます。
./skinny package
スタンドアロン jar をつくる
Jenkins や GitBucket などダウンロードしてきた war ファイルを java -jar ですぐに Web サーバとして起動できるのは非常に便利ですが、そういうファイルをすぐにつくることもできます*4。
こちらは素晴らしい sbt-assembly を使わせていただいていますが、skinny-blank-app.zip では既に諸々の設定がされているので、以下のコマンドを叩くだけ。
./skinny package:standalone
皆様のフィードバックをお待ちしています
Skinny Framework 1.0.0-RC1 を出しました。final の前にここだけはどうにかしろとかそういうフィードバックを頂けると非常に嬉しいです。final は 3 月後半予定。
— Kazuhiro Sera (@seratch_ja) February 22, 2014
NHK 番組表 API の Scala クライアント
http://api-portal.nhk.or.jp/ja
正式な開始は 1/27 みたいだけど、API キーも発行できるみたいだし、ひまつぶしに Scala クライアントを書いてみました。
実装は・・カッとなってやった感満載なので、気になる人は pull request とかいただければうれしいです。
https://github.com/seratch/nhk4s
sbt-sonatype を使ってリリースしました。問題なく使えました。すばらしいです。
http://search.maven.org/#search%7Cga%7C1%7Cnhk4s
NHK の API は確か去年の 6 月にリリースするということになっていましたが、おそらく前例もないことで色々大変だったんだろうと思います。中の方々、チャレンジ大変お疲れさまでした。
Play ドキュメントを Skinny で書くと - The template engine
これは Play framework 2.x Scala Advent Calendar 2013 の 18 日目です。
http://www.adventar.org/calendars/114
なお、この記事で触れる Play は 2.2.1、Skinny は 0.9.20 です。両者とも最新バージョンでは API や仕様が変更になっている場合があります。
The template engine
http://www.playframework.com/documentation/2.2.x/ScalaTemplates
Play2 は独自の Scala Template を持っており、最近では、この実装は Twirl という名前で単独のライブラリとして切り出されています。
https://github.com/spray/twirl
Twirl は Spray のプロジェクトの一部なのですが、最近 Spray も Typesafe のプロダクトになったので、この辺も将来的には統合されていくとかどうとか(あまり動向追ってない)。
Twirl は Play に依存していないので Scalatra など別のフレームワークとも組み合わせて利用することができます。みんな大好き GitBucket は Scalatra + Twirl ですね。
https://github.com/takezoe/gitbucket
一方、Skinny は Scalate を標準のテンプレートエンジンとしてサポートしています。
http://skinny-framework.org/documentation/view-templates.html
http://scalate.fusesource.org/
Scalate も基本的には事前に Scala コードに変換してコンパイルするアプローチですが、Skinny ではなるべくコンパイル待ち・リスタート待ちを減らしたフィードバックの早い開発を実現するために、デフォルトだと開発時はインタプリタ的に実行する設定になっています。
これのデメリットとして、全てのテンプレートに対して検証がされないだけでなく、初回アクセスのパフォーマンスも悪くなるので skinny package で本番向けにビルドする際は事前コンパイルするようになっています。
なお FreeMarker、Thymeleaf のサポートも拡張として存在しますが、最も Scala の表現力を活かせるのはやはり Scalate になります。Java 向けのテンプレートでは Scala メソッド呼び出しでかなり制限があるので、アプリケーションの性質によっては厳しくなりそうです。この辺は用途に合わせて判断されるのがよいかと思います。
それでは早速 Play のドキュメントのサンプルコードを見ていきます。
Overview
@(customer: Customer, orders: List[Order]) <h1>Welcome @customer.name!</h1> <ul> @for(order <- orders) { <li>@order.title</li> } </ul>
上記のような例は Scalate の SSP(Scala Server Pages) だとこのようになります。少し書き方が違うだけですね。
http://scalate.fusesource.org/documentation/ssp-reference.html
<%@ val customer: Customer %> <%@ val orders: List[Order] %> <h1>Welcome ${customer.name}!</h1> <ul> #for (order <- orders) <li>${order.title}</li> #end </ul>
Scalate は SSP 以外にも Scaml、Jade、Mustache をサポートしています。私は Jade がお気に入りなので、この記事では Jade のサンプルを多く紹介します。
Jade は Scaml をより簡潔に書けるようにしたものなので Scaml と Jade のリファレンスを併せて見るとほぼやりたいことが網羅されています。ここでは Jade を中心に説明しますが Scaml はタグを %li のように書く以外は Jade とほぼ同じになります。
http://scalate.fusesource.org/documentation/scaml-reference.html
http://scalate.fusesource.org/documentation/jade.html
-@val customer: Customer -@val orders: List[Order] h1 Welcome #{customer.name}! ul -for (order <- orders) li =order.title
Play Scala Template(Twirl)だと、コンパイル済のコードを controller から参照しますが*1
val content = views.html.Application.index(c, o)
Skinny では render メソッドに文字列で指定します。
render("/Application/index")
Play では app/views/Application/index.scala.html というファイルが存在する前提ですが Skinny では src/main/webapp/WEB-INF/views/Application/index.html.ssp が存在することが前提となります。
Syntax: the magic ‘@’ character
Play Scala Template(Twirl)では変数や for/if 式の始まりが @ からになりますが Scalate の場合は SSP と Scaml/Jade、Mustache でそれぞれ異なります。この辺は Scalate のドキュメントをご覧ください。
http://scalate.fusesource.org/
Template parameters
Play では、テンプレートが受け取るパラメータをこのように指定しますが
@(customer: Customer, orders: List[Order]) @(title: String = "Home") @(title: String)(body: Html)
それぞれ Jade だと
-@val customer: Customer -@val orders: List[Order] -@val title: String = "Home" -@val title: String -@val body: String
のようになります。
Iterating
<ul> @for(p <- products) { <li>@p.name ($@p.price)</li> } </ul>
Jade だと以下のようになります。インデントでスッキリと書くことが出来ますね。
ul -for (p <- products) li #{p.name} (#{p.price})
If-blocks
@if(items.isEmpty) { <h1>Nothing to display</h1> } else { <h1>@items.size items!</h1> }
Jade だと以下のようになります。こちらもインデントでスッキリと書くことが出来ますね。
- if (items.isEmpty) h1 Nothing to display - else h1 #{items.size} items!
Declaring reusable blocks
@display(product: Product) = { @product.name ($@product.price) } <ul> @for(product <- products) { @display(product) } </ul> @title(text: String) = @{ text.split(' ').map(_.capitalize).mkString(" ") } <h1>@title("hello world")</h1>
JSP に何でも書いちゃうノリで SSP でゴリゴリ実装すれば同じことは出来ますが、わざわざ紹介するようなやり方でもないですね...
<% def display(product: Product) = s"${product.name} (${product.price})" %> %for (product <- products) <%= display(product) %> %end
ユーティリティの class/object を用意して利用すれば特に問題はなさそうです。
Declaring reusable values
@defining(user.firstName + " " + user.lastName) { fullName => <div>Hello @fullName</div> }
私の認識が正しければ { .. } 内に限定して値を渡すことはできないですね。そこにこだわらなければ Jade だとこんな感じでやればよいと思います。
-@val fullName: String = user.firstName + " " + user.lastName div Hello #{fullName}
Import statements
@import utils._
SSP だと
<% import utils._ %>
Jade だと
- import utils._
のようになります。
Play だと build.sbt にあらかじめ
templatesImport += "com.abc.backend._"
とデフォルトの import を設定できますが Skinny では以下のクラスに
src/main/scala/templates/ScalatePackage.scala
/** Returns the Scala code to add to the top of the generated template method */ def header(source: TemplateSource, bindings: List[Binding]) = """ import com.abc.backend._ import com.abc.util._ """
のように指定します。
Comments
@********************* * This is a comment * *********************@
Scaml/Jade では
-# This is a comment Next line is also comment
のように -# のあと、インデントします。
Escaping
<p> @Html(article.content) </p>
デフォルトでエスケープされる点は同じです。エスケープしたくない場合は
p != article.content
または
p = unescape(article.content)
と指定してください。
Scala templates common use cases
http://www.playframework.com/documentation/2.2.x/ScalaTemplateUseCases
Layout
Play では views/main.scala.html で以下のようにしますが
@(title: String)(content: Html) <!DOCTYPE html> <html> <head> <title>@title</title> </head> <body> <section class="content">@content</section> </body> </html>
Skinny は src/main/webapp/WEB-INF/layouts/default.jade で同じことは以下のように記述します。拡張子を変えて ssp/scaml/mustache で記述しても問題ありません。また、このテンプレートを読み込む先と利用するエンジンが異なっていても構いません(views/root/index.html.ssp でこの jade を使用するのも OK)。
-@val title: String -@val content: String !!! 5 html head title #{title} body section.content #{content}
詳細はこちらをご覧ください。
http://scalate.fusesource.org/documentation/user-guide.html
@(title: String)(sidebar: Html)(content: Html) <!DOCTYPE html> <html> <head> <title>@title</title> </head> <body> <section class="sidebar">@sidebar</section> <section class="content">@content</section> </body> </html>
このテンプレートをこんな感じで使うと。
@sidebar = { <h1>Sidebar</h1> } @main("Home")(sidebar) { <h1>Home page</h1> }
Skinny ではまずテンプレートがこうなり(Jade の場合)
-@val title: String -@val sidebar: String -@val content: String !!! 5 html head title #{title} body section.sidebar #{sidebar} section.content #{content}
使う側はこのようになります。
-attributes("title") = "Home" -attributes("sidebar") = capture { h1 Sidebar -} h1 Home page
Jade だと取っ付きづらく感じられる方もいるかもしれませんので SSP の例もあげるとこのようになります。
<% attributes("title") = "Home" %> <% attributes("sidebar") = capture { %> <h1>Slidebar</h1> <% } %> <h1>Home Page</h1>
capture などについては User Guide をご覧ください。
http://scalate.fusesource.org/documentation/user-guide.html
Tags (they are just functions, right?)
views/tags/notice.scala.html のようなファイルに関数を定義しておけば taglib 的に使えるよ、という感じのものですが Scalate では普通に object つくってそれを import して使えばいいという感じのようです。
Includes
テンプレートの中で普通に render を呼べば他のテンプレートを include できます。例えば Jade のファイルと同じ階層に hello.ssp がある場合、以下のように指定するだけです。
= render("hello.ssp")
moreScripts and moreStyles equivalents
Play では @routes.Assets.at のように呼び出すと assets のパスを解決してくれますが Scalate では ContextPath を考慮した形でパスを設定してくれる uri/url というメソッドが使えます。以下は Jade の例です。
script(type="text/javascript" src={uri("/assets/js/jquery-2.0.3.min.js")}) link(rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.1/css/bootstrap.min.css")
以下と同じことは capture でできますね。
@scripts = { <script type="text/javascript">alert("hello !");</script> }
明日・・・
ぶっちゃけ明日の記事は書いてないですし、ちょっとそろそろアレな感じです。明日、誰もいなかったら途切れてしまうかも・・
http://www.adventar.org/calendars/114
誰かの参加をお待ちしていますね・・って、私は一体何なのだろう。
*1:逆に言えば view がまだなかったら controller のコンパイルが通らない