play2.0のフォームでbind以後にエラーを追加する

import play.api.data.FormError

var form = Form(mapper).bindFromRequest
if(エラー条件){
  form = form.copy(errors = form .errors ++ Seq(FormError("フィールド","error.message",arg1)),value=None)
}

form.fold(
  errorForm => BadRequest(views.html.error(errorForm)) // エラー画面に遷移
  value => Ok("ok")// 成功
)

valueがNoneじゃないとfoldでエラーに遷移してくれない。foldを使わないならvalue=Noneは必要なくてそのままエラー画面に遷移すればよい

specs2 よくある変換関数のテスト

scalaのテストフレームワークspecs2 で、icu をラップした String => String 関数のテストとかはこういう感じ

import org.specs2._
import org.specs2.specification._
import org.specs2.execute._
import org.junit.runner.RunWith
import org.specs2.runner.JUnitRunner

@RunWith(classOf[JUnitRunner])
class KanaServiceSpec extends Specification {
  def is = sequential ^
    "hurigana" ^ when(KanaService.hurigana) ^
    "ひらがな ${あるの} は ${アルノ}"     ^ then ^
    "半角 ${アルアノリウ} は ${アルアノリウ}"   ^ then ^
    "trim ${ アルアノリウ } は ${アルアノリウ}" ^ then ^
    "濁音 ${ダダ} は ${ダダ}"             ^ then ^
    "半角濁音 ${ダダ} は ${ダダ}"         ^ then ^
    "全角濁音 ${タ゛ー} は ${ダー}"       ^ then ^
    p^
    "initialLetter" ^ when(KanaService.initialLetter) ^
    "ひらがな ${あるの} は ${ア}" ^ then ^
    "半角 ${アルアノリウ} は ${ア}"     ^ then ^
    "trim ${ アルアノリウ } は ${ア}"   ^ then ^
    "濁音 ${ダダ} は ${タ}"       ^ then ^
    "半角濁音 ${ダダ} は ${タ}"   ^ then ^
    "全角濁音 ${タ゛} は ${タ}"   ^ then ^
    end

  def when(f:String => String)= new Given[(String => String)]{
    def extract(text:String) = f
  }
  def then = new Then[(String => String)]{
    def extract(addition: (String => String), desc: String): Result ={
      val x = RegexStep.extract2(desc)
      addition(x._1) must_== x._2
    }
  }
}

このwhenとthen、もうちょっと汎用化できそう、というか既に定義されていそう。教えてください……

一応参考までにテストされるクラスはこんな感じ(型だけ)

object KanaService{
  def hurigana(str:String):String = str.xxxxx
  def initialLetter(str:String):String = str.xxxxx
}

play2.0 でspecs2とscalatestを両方使う

appDependencies足しただけだと

[error] Could not run test test.ApplicationSpec: java.lang.IllegalArgumentException: Unrecognized argument: sequential
Throwable escaped the test run of 'test.ApplicationSpec': java.lang.IllegalArgumentException: Unrecognized argument: sequential
java.lang.IllegalArgumentException: Unrecognized argument: sequential
	at org.scalatest.tools.ScalaTestFramework$ScalaTestRunner.parsePropsAndTags(ScalaTestFramework.scala:286)
	at org.scalatest.tools.ScalaTestFramework$ScalaTestRunner.run(ScalaTestFramework.scala:137)

とかエラー出る。
http://seratch.hatenablog.jp/entry/20120401/1333269471
参考に

      testOptions in Test := Nil

するとscalatest動くけどjenkins用のxml吐いてくれない。いろいろ探し回った結果 Build.scala

object ApplicationBuild extends Build {
  :
  val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA).settings(
    :
    testOptions in Test := Nil,
    testOptions in Test += Tests.Argument(TestFrameworks.Specs2, "sequential", "true"),
    testOptions in Test += Tests.Argument(TestFrameworks.Specs2, "junitxml","console"),
    testOptions in Test += Tests.Argument(TestFrameworks.ScalaTest, "junitxml(directory=\"target/test-reports\")")

sbtではこんな風に書くと各テスト用のオプションを使い分けられるらしい。

sbtでは http://scalajp.github.com/sbt-getting-started-guide-ja/more-about-settings/ を見ると ~= でオプション書き直せるらしいけどやり方がよく分からなかったので再設定している(しかも中途半端)誰かちゃんとして……
というかplayのほうで最初からspecs2用オプションだって宣言してくれたらいいのに……

iniファイルをコマンドラインからアップデートするツール update_ini.pl

awkなどから編集しやすそうで微妙に編集しにくいiniファイルをコマンドラインから編集するperlスクリプトを作りました。

一つのファイルだけで動作するので

 wget https://raw.github.com/nazoking/update_ini/3d2668e5501822b017785a21c143576e577f2cf8/update_ini.pl

で適当な場所において

 sudo perl update_ini.pl /etc/my.cnf [mysqld] default-charcter-set=utf8

のように実行すると /etc/my.cnf が書き換わります。一応バックアップが /etc/my.cnf.bak として作成されます。書き換え指示はファイルでも出来て

 sudo perl update_ini.pl --input diff-my.cnf /etc/my.cnf

のように書きます。

ソースは
https://github.com/nazoking/update_ini

ご利用ください。

初めてperlのオブジェクト的なのとテストを書いたのでその辺の書き方のツッコミとかもお待ちしております。
あと探したけど見つからなかったから作ったので使える別のツールの紹介もお願いします(;´Д`)。perlに変なモジュール入れなくても動くかcentos5で簡単に動くことが条件。

VirtualPCで安全にサーバを立ててホストOSからアクセスする

モチベーション

ネットワーク設定をNATにするとホストOSからゲストOSのIPにアクセス出来ない。かといって他のアダプタにバインドするとホストOS以外からアクセスできてセキュリティー的な事気をつけないといけなくなって面倒くさいですよね……あとネットワークに接続してないときにIPなくなるしノートで無線と有線とemobile使い分けてたりとかすると毎回設定変更しないといけなくなるし、ホストがDHCPだとゲストも毎回IP変わる。

方法

NATとLoopback Adapterを使います。ゲストOSからはNAT経由でインターネットに出る。ホストOSからゲストOSにアクセスするにはLoopback Adapterを使います。

  • ホストにMicrosoft Loopback Adapterをインストール
    • Loopback AdapterのIPを固定IPにする
    • 仮想マシンの設定でネットワークの設定を
      • アダプターの数 2
      • アダプター1 共有ネットワーク(NAT)
      • アダプター2 Microsoft Loopback Adapter
  • ゲストでもネットワークが二つ認識されているはず
    • eth0 はDHCP
    • eth1 は固定IP。ただしゲストのIPとは同じネットワークの別のIPにする

ホストでloopbackを192.168.199.1 とかにしたらゲストは192.168.199.2 とかに。ゲートウェイは設定しない(インターネットの外に出るにはeth0のNATの方のアダプターを使う)

これで 192.168.199.2 でゲストOSにアクセスでき、ゲストから外に出るときはeth0→NAT→ホストOS→ホストOSのネットワーク設定に従って繋がってるネットワークに出て行きます。

参考

onclickなどでjqueryっぽいイベントを仕掛ける


jQueryでエレメント生成と同時に$(hoge).click(hogeOnclickCallback) みたいなのやってると、その内どんなイベントがフックされてどこに飛ぶのか分からなくなってしまう。みんなどうやってるんだろ。

jQuery-templateとhtmlのイベントアトリビュートで設定するようにするとhtmlインスペクタで見れば何のイベントでどこに飛ぶか分かるからいいんじゃないかなぁと思って作った。onclick="hogeOnclickCallback.ev(this,event)"のように仕掛ける。