Play で conf/ 以下のファイルを扱う場合の注意点


Play では conf/ 以下に設定ファイルや、マイグレーション用の sql を置きます。
場合によってはちょっとした画像をファイルを置くこともあるかもしれません。例えば、アプリ起動時にアスキーアートを表示するためにその素材を置くとか。あると思います。


この conf/ 以下のファイルをアプリケーションから参照する際には Application#getFile または Application#resource が使えます。


まずは、普通にファイルとして扱う Application#getFile。これは引数として、プロジェクトルートからの相対パスを渡します。

val file: File = app.getFile("conf/sample.png")


一方、resource はリソースファイルとしてアクセスする API です。
conf/ は実は Maven プロジェクトで言うところの src/main/resources です。

val resource: Option[URL] = app.resource("sample.png")


で、結論としては、Application#getFile ではなく Application#resource を使いましょう。


Application#getFile を使うと play run や play start でアプリを起動する分には良いのですが、
play dist でデプロイした場合には conf が dist には含まれないのでファイルが参照できなくなります。


詳しくはここ -> https://github.com/playframework/Play20/issues/1079
getFile 変じゃね? って話がされてます。getFile は 2.2 で deprecated になるみたいですね。

dist で conf/ をコピーするって案も出てますが、それも無理があると思いました。自分も getFile 要らないと思います。


play-flyway でもこれに引っかかったので、修正しました。見つけて下さった yasushia さんありがとうございました。
https://github.com/tototoshi/play-flyway/issues/4

Play 2.2, 2.3 Roadmap

https://docs.google.com/document/d/11sVi1-REAIDFVHvwBrfRt1uXkBzROHQYgmcZNGJtDnA/pub

Scala の重要と思うとこだけピックアップ。

2.2

Typesafe Activator

Typesafe Activator っていうブラウザからプロジェクトのテンプレートを作ったり、開発できたりしちゃうなんだかすごいもの(なんだかすごいので是非触ってみましょう)があり、それのサポートが進められます。

使用する sbt が 0.13 になる

バージョン上げるだけと思ったあなた。残念でした! sbt ですよこれは!
sbt は 0.13 で build.sbt がパワーアップするので、今 Build.scala で設定しているのを build.sbt に移行しようっていう計画のようです。

ivy リポジトリ、ドキュメント機能の変更

今まで Play は ivy のリポジトリをデフォルトの ~/.ivy2 ではなく、$PLAY_HOME/repository を使っていましたが、これをやめるようです。

それから Play のドキュメントが

http://localhost:9000/@documentation

で見られるというあまり有名じゃない機能があるんですが、この機能が修正されます。

おそらくどちらも理由は Typesafe Activator を推すのに、Play 独特のやり方ではまずかったってとこでしょう。Typesafe Activator、別にどうでもいいんですが、これのおかげで Play の仕組みが Scala のエコシステムにマッチする方に向かうと考えるポジティブさよ。

API の変更
  • Form と Json で統一感を出すため、API が変わります。
  • Results のリファクタリングされたみたいで、API が変わります。(それリファクタリングじゃないと思います)
  • Iteratee API が変わります。
  • ドキュメントやテストインフラの改善。これについてはまだぼんやりとしか書いてない。やるやる詐欺かも。

2.3


まだまだ先でぼんやりしてますが、一つだけでかいのありますね。

Anorm -> Slick

最初からオワコン臭が漂っていた Anorm が切り離され、Slick がデフォルトになります。すでに Play には play-slick(https://github.com/freekh/play-slick) を元に、Slick を統合するための pull request がされています。
今から Play アプリを作る人は Anorm ではなく、Slick を使うと良いと思います。

ちなみに Java は Ebean から JPA に変わるそうです。いや〜 JPA、いいですね。あ、私は今日 Hibernate/JPA のバグで 5 時間くらい無駄にしました。みなさん、苦しみをわかちあいましょう。

sbt のプロンプトに git のブランチ名を表示させる

sbt は簡単にプロンプトが変えられることはご存知でしょうか。


build.sbt で shellPrompt を定義するだけです。
shellPrompt の型は SettingKey[State => String] なので := の右側には State => String という型の関数を定義します。
state ってなにって感じですが、簡単なものならとりあえず気にせずに設定できます。


固定の文字列を返すパターン

shellPrompt := { state => "( ゚A゚ )> " }


毎回変わるパターン

shellPrompt := { state => (new java.util.Date).toString + "> "}


よしださんがこの機能を使って git のブランチを表示させることをやっていて、

shellPrompt := { state =>
  Project.extract(state).currentProject.id +
    "git branch".lines_!.find{_.head == '*'}.map{_.drop(1)}.getOrElse("") + "> "
}


便利そうだったので、だいたいそんな感じのやつを sbt-git にプルリってマジられました。
git のブランチを zsh で表示させるとかは結構前からやっていてすごく便利。

https://github.com/sbt/sbt-git/pull/17

あと stash の状態とかも付け足すしても便利かなあ。


shellPrompt でむずかしいのは、すでにカスタマイズしてる人の設定とぶつかってどっちかが上書かれちゃうってとこですね。うまく合成できたらいいんですが。今回はあまり考えないことにしました。

コンパイル中に音楽を流せる sbt プラグインを作りました。

Scalaコンパイルが遅い件は「Scala コンパイル 遅い」とかで適当にググればいいと思います。
https://twitter.com/search?q=Scala%20%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%AB%20%E9%81%85%E3%81%84


コンパイルが遅いと開発速度が当然鈍りますから、Scala にとっては大きな課題なわけですが、バージョンが上がり機能が増えていけば行くほどコンパイル時間は長くなる傾向にあります。
またマクロや implicit conversion などのコンパイル時に解決を行うような機能を多用したりしてもコンパイル時間は長くなります。
解決策としては

  • 良いマシンを買おう!!

です。

でも良いマシンを使っても遅いもんは遅いです。で、解決策を考えたのですが、思ったんです。逆に考えたらいいんじゃないかって。コンパイル時間長くたっていいんじゃないかって。


というわけで sbt-musical という SBT プラグインを作りました。


https://github.com/tototoshi/sbt-musical


sbt-musical を使うとビルドの間に音楽を流せます。

インストール

まず、bash-itunes というコマンドラインツールをインストールしておいてください。

$ mkdir ~/bin  # if not exists
$ curl https://raw.github.com/illusori/bash-itunes/master/itunes > ~/bin/itunes && chmod 0755 !#:3


次に ~/.sbt/plugins/build.sbt に次の1行を加えます。

addSbtPlugin("com.github.tototoshi" % "sbt-musical" % "0.1.1")


以上です。

注意点ですが、bash-itunesiTunesAppleScript で操作しているので、Mac でしか動きません。
sbt-musical では bash-itunes をラップした scala-itunes (https://github.com/tototoshi/scala-itunes) を使っているので、Windows 対応したければ、scala-itunes に pull request ください。

使い方

「♪」をコマンドに頭につけます。

> ♪ compile

分かりやすいでしょ。そしてずいぶん楽しげなコマンドに見えます。
これでコンパイルしてる間に音楽が流れます。コンパイルが終わると止まります。

「♪」は任意のコマンドに対して使えます。例えば

> ♪ test

これでテストしてる間に音楽が流れます。テストが終わると止まります


ソースの変更を検知してコマンドを連続で実行させる「~」と組み合わせることも可能です。

> ♪ ~compile


ついでな感じですが、iTunes の簡単な操作をするコマンドもつけています。

再生

> itunes-play

一時停止

> itunes-pause

音量設定

> itunes-vol 50

または

> itunes-vol up/down

効果

これで、コンパイル時間の間に好きな音楽を流せるようになるので、コンパイルが楽しくなります。コンパイル時間が長くなるほど音楽がたくさん聞けます。というかコンパイル時間が短いと曲が細切れになりすぎるので逆にイライラしてきます!


選曲についてはお任せしますが、割りとテンションの上がる曲のほうが、「コンパイルはじまったああああ!!!」感があるのでオススメです。逆に落ち着きたい人はお経でも流せばいいんじゃないっすかね。


あと作って初めて気がついたんですが、コンパイルが終わると音楽が止まるので、「コンパイルなげえわ〜」とネットサーフィンし始めてもコンパイルが終わったのにすぐ気づくので時間を無駄にしません。


これで Scalaコンパイル時間の長さは解決されました(断言)。皆さんたくさんコンパイルしましょう。

Play 2.0 と 2.1 での Akka Actor の使い方の違い

Play を使おうとしたら、全然パフォーマンスがでない、なんで? → Akka のチューニングが必要だった。
という話は Play 2.0 の頃から結構有名な話でした。

http://qiita.com/items/0c4bb34a420665536db4
http://tech.furyu.jp/blog/?p=2069
http://gendosu.jp/archives/1945

Play 2.0 では

  • Request に対して BodyParser を適用するところ
  • Action のディスパッチ

の 2 箇所で Akka が使われていました。
コードで言うとここらへん、ActionInvoker というクラスです。
https://github.com/playframework/Play20/blob/2.0/framework/src/play/src/main/scala/play/core/system/Invoker.scala#L65-L94


さて、Play 2.1 では実はここのコードがごっそりとなくなっています。
Play 2.1 から EssentialAction というものが導入されたのですが、それに伴う変更のようです。

https://github.com/playframework/Play20/commit/7d4f7ef05f32b8dd80f8f93d7362948f27c098b4

今まで Actor を使っていたところが、scala.concurrent.Future ベースで書きなおされています。


ということは、Akka のチューニングってもう要らないわけ?と思ったのですが、そういうわけではありません。
Future のための ExecutionContext に Akka の dispatcher を使っていました。
akka の dispatcher は ExecutionContext インタフェースを実装しているらしい。
https://github.com/playframework/Play20/blob/2.1.0/framework/src/play/src/main/scala/play/core/system/Invoker.scala#L23

というわけで、Akka のチューニングはやっぱり必要みたいです。

感想

  • Akka はまだ使われているが、Akka Actor を使ったコードは表に出なくなった。
  • 単純な非同期プログラミングをするなら Actor じゃなくて scala.concurrent.Future のほうが良い。
  • Akka って良くできてる。

sbt-install 作った

https://github.com/tototoshi/sbt-install

sbt は manual install するのが好みなんですが、

あっ、このマシン sbt 入ってない

とか

あっ、sbt が古い

ってときに例の java -jar sbt-launch.jar するスクリプト書くのがいい加減めんどくさくなったので、インストールスクリプト作っときました。
0.12.x 系は launcher は共通なのでそんな必須でもないんですが、そうは言っても sbt ってすぐアップデートされちゃうし。。。

$ curl https://raw.github.com/tototoshi/sbt-install/master/sbt-install > ~/bin/sbt-install && chmod 0755 !#:3 

でインストールスクリプトをインストールできます。
そんで、

$ sbt-install 0.12.3

で sbt 0.12.3 をインストールできます。

プロジェクトによってはプロジェクトのリポジトリに sbt-launch.jar に入れてしまうこともあると思うので
-d でインストールするディレクトリを選べるようにしました。

$ sbt-install -d . 0.12.3


地味に便利だと思います。

sbt version manager みたいなのにしようかとか思ったけどすぐにそれはやりすぎだと思いました。

ヘッダーを見て cut するコマンド作った

データ処理でヘッダーがついてるtsv形式のデータファルを扱うことがあるんですが、フィールドが何番目か数えてから cut コマンドをするのがめんどいし、cut -f 1,3,12 みたいなのが暗号めいてていやなので、ヘッダーを指定して cut できるコマンドを作りました。地味っすね。


こんな感じ。

$ cat a.txt
USER_ID NAME    AGE
1       Sato    10
2       Suzuki  30
3       Abe     20
$ hcut -f USER_ID -f NAME a.txt
1       Sato
2       Suzuki
3       Abe


PyPI に挙げたので easy_install hcut で入ります。