2012年振り替えるよ
今年もあと2時間。
色々チャレンジした年であり、新たに始まったことが多かった年でした。
が、反面、反省も多かった。
Jenkins本に寄稿した
これ今年でした。作業したのは2011年だけど。。
- 作者: John Ferguson Smart,Sky株式会社玉川竜司
- 出版社/メーカー: オライリージャパン
- 発売日: 2012/02/22
- メディア: 大型本
- 購入: 12人 クリック: 334回
- この商品を含むブログ (32件) を見る
Playframeworkコミッターになった
2.0が出た関係で1.x系のメンテナーが足りず、協力を申し出てそのままコミッターになりました。
が、この件は反省が多いです。メンテナーになっておきながらほとんど貢献できず、負い目を感じる局面が多かった。。
言い訳になってしまいますが、本業が大分忙しくなった(新規のプロジェクトを複数持ってた)のに加え、プライベートな時間も色々とあって、メンテナーの仕事がなかなか出来なかったです。
1.2.6あるいは1.3を待ってる方もいることですし、この件はなんとか時間を作っていきたいと思います。
Play勉強会、第三回やれた
一年に一回しか出来てませんが、とりあえず今年もPlayframework勉強会やりました。
年末には忘年会もやりました。
そこでも希望が多かったですが、来年はもくもく会でいいから定期的にユーザー会やろうと思います。
JJUG CCC 2012 Spring で講演した(2013年1月15日追記)
WEB+DB Press に Play 企画書きました
おい、美輪さんヨイトマケ歌ってるよ。びっくりした。
前年からPlayについて本書こうとか記事書こうとかそういう話が浮かんでは消えしてたんですが、技評の春原さんの助けもあって、やっと形になりました。
一緒に書いてくれた梅澤さん、九岡さん、ありがとうございました。
- 作者: 竹迫良範,Jxck,じょさん,後藤秀宣,藤原俊一郎,奥野幹也,堤智代,森田創,中島聡,A-Listers,はまちや2,相澤歩,柴田博志,池田尚史,梅澤雄一郎,九岡佑介,近藤宇智朗,佐藤鉄平,mala,WEB+DB PRESS編集部
- 出版社/メーカー: 技術評論社
- 発売日: 2012/10/24
- メディア: 大型本
- 購入: 12人 クリック: 159回
- この商品を含むブログ (10件) を見る
職場に Scala チーム作った & 新製品リリースした
こう見えて僕は部署を持ってたりするのですが、今年はたくさんのエンジニアを採用させていただき、Scala チームの編成に頑張ってみました。
Scala をやったことある人なんて全然いないので、採用の時に Scala でもいいですか? なんて聞きながらでしたが。皆楽しんで Scala に取り組んでくれたのでよかったです。
詳しいことは書きませんが、Scala + Play2 で新製品も出せましたしね。
来年の抱負
来年のことを言うと鬼がわらいますので特に言いませんが、やりかけてるものはきちんといい形で終わらせますのでよろしくお願いします。各位。
ご迷惑おかけしている方々、ほんとすいません。
さて、今年もありがとうございました。もろもろみなさんのおかげです。
来年もよろしくお願いします。
スラッシュ付きとスラッシュなしURLの扱いとPlay2での逃げ方
Play2でスラッシュ付きとスラッシュ無しで別のRouteとして扱われちゃって面倒くさいという問題があったと思いますが。
ここでも議論になっています。
James Roperの言うように、Global.scalaにコード書けば、一応問題は避けられそうです。将来的にはこれはPlay内に機能として持ったほうがいいコードだと思いますが。。
ちなみにこの辺についてどう対応するのが正しいのかについては、下記Googleのサイトが参考になります。(上記チケット中にもリンクあり)
http://googlewebmastercentral-ja.blogspot.jp/2010/11/url.html
Jamesが提示したように、片方を200にして片方を301にするっていうのがあるべき姿みたいですね。
Play2 + Scala のカバレッジツールで一番マシなのは scct かな?
この記事は Play or Scala Advent Calendar 2012 12/10 分の記事です。
使ってる Play のバージョンは 2.0.4 です。Scala のバージョンは 2.9.1 ですよ。
なんかjacoco4sbtだめ
以前jacocoとjenkinsの記事を書いたんですが、jacocoだと余計なカバレッジまで計測してしまう(下記画像参照)ので困っていました。play new して作ったプロジェクトに、 GET / するテストを書いただけなのでカバレッジ100%になるはずなのに、異常にカバー率が低い。。
この場合RoutesやらReverseやらのPlayがジェネレートしているコードが邪魔なので、下記のように除外設定を書けば少しはましになりますが。
//Build.scala jacoco.excludes in jacoco.Config := Seq( "views.html.*", "Routes*", "*Reverse*", "views**", "routes*" )
でもまだまだダメ。例えばApplication.scalaのレポートをみると、、なんじゃこりゃー。。
Controllerトレイトの実装まで全部カバレッジレポートの対象にしちゃうので見にくくてしょうがない。
scctかな?
で、scctを試してみました。
潔いくらいドキュメントがない! のですが、導入は簡単です。機能も少ないし。
ちなみに Usage のところに sbt0.12 以上って書いてあるけど、無視しました。*1
使い方
Build.scalaはこう。
import sbt._ import Keys._ import PlayProject._ object ApplicationBuild extends Build { val appName = "coveragesample" val appVersion = "1.0-SNAPSHOT" lazy val s = Defaults.defaultSettings ++ Seq(ScctPlugin.instrumentSettings: _*) val appDependencies = Seq( // Add your project dependencies here, ) val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA, settings = s).settings( // Add your own project settings here parallelExecution in test := false ) }
ポイントは、
- scctの設定を追記する
lazy val s = Defaults.defaultSettings ++ Seq(ScctPlugin.instrumentSettings: _*)
- PlayProjectのsettingsプロパティに上記設定をセット(settings=sのところね)
val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA, settings = s)
です。*2
あと、parallelExecution in test := false も忘れない様につけておきましょう。これをつけないとテストが並列で実行されてしまいます。困りますよね? 僕は困ります。*3
で、plugins.sbtあたりにこう。
resolvers += Classpaths.typesafeResolver resolvers += "scct-github-repository" at "http://mtkopone.github.com/scct/maven-repo" addSbtPlugin("reaktor" %% "sbt-scct" % "0.2-SNAPSHOT")
これで下記のように実行すればいいです。
$ play scct:test
下記のような結果が得られます。
RoutesやReverseが含まれちゃってるのはjacocoのときと変わりませんが、Application.scalaの中を覗くと、余計なものが含まれてなくて綺麗だね!
さらにscctさんはcobertura互換のxmlも吐いてくれてます。なのでこいつをJenkinsに食わせましょう。
Jenkinsにセット
手順としては
- 事前準備:必要な(Jenkinsの)プラグインが入ってなければいれておく
Coberturaプラグインが入ってない場合はいれておきましょう。他にもGitを使うのであればGitのプラグインなどを入れましょう。
- フリースタイルジョブを作る
- "設定 > ビルド > シェルの実行" を選択し、下記をセット
/path/to/play-2.0.4/play clean /path/to/play-2.0.4/play test /path/to/play-2.0.4/play scct:test
パスは適切に設定してくださいね。
play test と play scct:test と、テストを2回実行しているのには理由があって、play testはJUnitのXMLを吐くため、play scct:testはカバレッジレポートを吐き出すため、です。ダサいですね。ごめんなさい。。
2つ合わせて下記の感じで。
Coberturaプラグインのインストールを忘れてると"ビルド後の処理 > Coberturaカバレッジレポートを集計" が出てこないので注意。
その他、SCMからコードを取得してくる設定とかは適宜やってください。
設定を上手いことやって実行すると、下記のような結果が得られます。カバレッジの推移も見れますね。
Application.scalaのレポートもバッチリですね。
JUnitの結果も集計できています。いつからデグったのかとか、わかり易くていいですね。
課題
手が回らなかったけど、いずれ解決したい課題
まとめ
Routes やら Reverse やらのジェネレートされたコードがカバレッジ対象に含まれちゃうのは jacoco と変わりませんが、フレームワークのコード(Controller トレイトなど)が混ざらない分、scctの方がマシそうです。
多分除外設定書くのも難しくないし。
内部では Scala Compiler Plugin として実装されているので、コード読むのも面白いです。
みんなでパッチ送って育てましょう。
2012/12/10 19:00追記
なんか、Playプラグインを使ってると scct:test がうまく動かないみたいです。会社のメンバーが教えてくれました。
play.plugins とか、その辺のファイルがないって怒られるっぽい。
なので、下記のようなスクリプトを会社の人が書いてくれました。play test と play scct:test の間に実行するといいみたいです。
#!/bin/bash [ -z "$1" ] && echo "Usage: $0 PATH_TO_PLAY_COMMAND" && exit -1 echo "exec: $1 scct:compile" $1 scct:compile echo "... copy some files for scct:test" for i in `find ./target/scala-2.9.1/classes -type f`; do TARG=`echo $i | sed -e "s/\/classes\//\/scct-classes\//"`; [ -f $TARG ] || echo "Copy $i"; [ -f $TARG ] || [ -d `dirname $TARG` ] || mkdir -p `dirname $TARG`; [ -f $TARG ] || /bin/cp $i $TARG; done echo "exec: $1 scct:test" $1 scct:test
使い方としてはこんな感じ
export PATH=/usr/java/jdk1.6.0_37/bin/:$PATH /usr/local/play-2.0.4/play clean /usr/local/play-2.0.4/play test ./scct-test.sh /usr/local/play-2.0.4/play
根本的には、play-scct プラグインを書かないといけないですが、それはまた別の機会に。。(早ければ年末!)
*1:Play2.0.4 は sbt0.11.3 を使用しています
*2:ちなみにこの辺の settings とかの書き方って、いろんな書き方ができるので実は上記のとおりに書かなくてもいいのです。奥が深いというか、sbtを理解すればいろいろ捗るのかもしれないので覚えてみてはいかがでしょうか。
*3:sbtさんは親切でつけてるんだと思うけど、勝手にテストを並列に実行されて嬉しい人いるんだろうか。。それが必要なときはCIサーバを増やしてCIサーバ側(要はJenkins)で並列実行するんだから余計なことしないでいいと僕は思うんだけど。。
*4:これはscct自体に機能がない。既に要望は上がってるんだけど、本人にヤル気がなさそう。なんで必要なのか分からんって、言うけど、Playには必要なんだよ!! https://github.com/mtkopone/scct/issues/31
Salat(play-salat)で日付型のカラムにJodaTimeを使う方法
Play Scala でアプリを作る際、データベースにMongoDBを採用するってのは、結構ある話かなと思います。
PlayでMongoDBを使おうと思うと、play-salat を使うことになると思います。SalatはMongoDB用のORMです。
SalatでJoda Timeを使う方法をメモ書きしておきます。
下記をインポートするといいです。
RegisterConversionHelpers() RegisterJodaTimeConversionHelpers()
Salat、というかPlay-Salatを使う場合、下記のようなパッケージオブジェクトを作っておくと思うのですが、
package models import com.novus.salat.dao._ import com.novus.salat.annotations._ import com.mongodb.casbah.Imports._ import com.mongodb.casbah.commons.conversions.scala.{RegisterConversionHelpers, RegisterJodaTimeConversionHelpers} import com.novus.salat.{ TypeHintFrequency, StringTypeHintStrategy, Context } import play.api.Play import play.api.Play.current package object mongoContext { RegisterConversionHelpers() RegisterJodaTimeConversionHelpers() implicit val context = { val context = new Context { val name = "global" override val typeHintStrategy = StringTypeHintStrategy(when = TypeHintFrequency.WhenNecessary, typeHint = "_t") } context.registerGlobalKeyOverride(remapThis = "id", toThisInstead = "_id") context.registerClassLoader(Play.classloader) context } }
上記のように、この中に宣言してやるといいです。
あとは各モデルクラスの中で、下記のようにパッケージオブジェクトをインポートしてやればいい感じにJodaTimeを使えます。
package models import play.api.Play.current import org.joda.time.DateTime import com.novus.salat._ import com.novus.salat.annotations._ import com.novus.salat.dao._ import com.mongodb.casbah.Imports._ import se.radley.plugin.salat._ import mongoContext._ case class Hoge(fuga: String, baz: String, date: DateTime) object Lead extends ModelCompanion[Hoge, ObjectId] { val dao = new SalatDAO[Hoge, ObjectId](collection = mongoCollection("Hoge")) {} def findOneByVisitorId(fuga: String): Option[Hoge] = dao.findOne(MongoDBObject("fuga" -> fuga)) }
sbtで社内Mavenリポジトリにパブリッシュ
社内に簡素なMavenリポジトリ(Nexusみたいなリッチなものを使ってなくてsshと80番しか開けてないようなの)を構築していて、作ったライブラリをそこにパブリッシュしたい場合、下記のように設定すると上手く動く。というメモ。
build.sbt にこんなふうに書いて、
publishMavenStyle := true publishTo <<= (version) { version: String => val rootpath = "/path/to/maven repo/" val path = if (version.trim.endsWith("SNAPSHOT")) rootpath + "snapshots/" else rootpath + "releases/" Some(Resolver.sftp("My Maven Repo", "my.maven.repo.domain", path) as("username", "password" ) ) }
下記のようにすれば、パブリッシュ出来る*1。
$ sbt publish
Nexusを使ってる場合のサンプルは比較的見つかったけど、それ以外のケースが見当たらなかったのでメモとして書いておく。
sbtって難しいよね。色々出来るようにしてるのは分かるんだが、正直調べるのも理解するのも面倒。
よくある業務パターンに応じた設定テンプレートみたいなのをドキュメントとして作って行かないと、色々つらいなあとか思いました。
*1:ちなみにsbtのバージョンは0.11.3で確認