seratch's weblog in Japanese

About Scala, Java and Ruby programming in Japaense. If you need English information, go to http://blog.seratch.net/

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 ?

こんな記事もありましたが

Scalate 1.7を試してみる - Starlight

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: をお願いしたところ

無事マージされました。ありがとうございます!

ということで Scalate の公式サイトはこちらになりました。

Scalate

Skinny Framework からのリンクも更新しておきました。

https://github.com/skinny-framework/skinny-framework.github.io/commit/2c0c7fcfc0c739c761b72433a12db0b5d937cce4

最近は 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 のスターがかなり増えていますね。また、手前味噌ですが ScalikeJDBCSkinny 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でメンテされる状況をつくることができればいいと思っています。ということで、既に関わってくださっている方々にはとても感謝しております。いつもありがとうございます。

*1:なお、もちろんスター数が多いからよいライブラリとは限らないのですが、必要条件ではあるとは思います

*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 を下さった全ての方に感謝いたします。

公式ドキュメント

こちらです。全て英語ですが、私が書いているので全部平易な表現で書かれています。

http://skinny-framework.org/

試す

Skinny Framework はすぐに試せます。JDK さえ入っていれば Mac OS XLinuxWindows を問わず 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

http://localhost:8080/members

にアクセスすると members テーブルの CRUD 画面が動作していることを確認できます。

テストを実行する

テストも大事ですね。db:migrate を忘れずに。

./skinny db:migrate test
./skinny test

カバレッジ計測も大事ですね。ということで scoverage を使えるようにしていますが

https://github.com/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

皆様のフィードバックをお待ちしています

*1:本当はもっと便利なものを入れたかったけど、ちょっと最近色々忙しいもので...これからも継続してやっていきます

*2:デフォルトの DB は SQLite3 ではなく、ローカルファイルの H2 Database ですが

*3:db migrate してない状態で model クラスをロードするとエラーになります

*4:拡張子は jar ですが

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

NHKAPI は確か去年の 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 のコンパイルが通らない