読者です 読者をやめる 読者になる 読者になる

Play2+Scalaでのバリデーションについて:verifyingを一度に複数利用する際の注意

verifyingを利用する上で注意すべきこと

先日verifyingを一度に複数利用できることを紹介しました。
記事を作成した時点では気がついていなかったのですが以下の様な場合、注意が必要です。

  val form = (id:String) => Form(
    tuple(
      "old" -> nonEmptyText,
      "new" -> nonEmptyText,
      "confirm" -> nonEmptyText
    ) verifying("新しいパスワードと確認用パスワードが一致していません", result => result match {
      case (old,newPass,confirm) => newPass == confirm
    }) verifying("古いパスワードと新しいパスワードが同じです",result => result match {
      case (old,newPass,confirm) => old != newPass
    }) verifying ("パスワードの更新に失敗しました",result => result match {
      case (old,newPass,confirm) => User.updatePassword(id,old,newPass)
    })
  )   

この例ではユーザーのパスワードの更新を行おうとしています。
ただしこの例では期待通りの動作はしません

もしこのままであった場合、3つの要素に対するバリデーションのどこかでエラーがあった場合でもパスワードが更新されてしまいます

つまりどこかでエラーがあった場合でもエラーがあった場所で評価をやめるわけではなく、すべて評価を行うというわけです。
この問題を改善すると以下のようになります。

  val form = (id:String) => Form(
    tuple(
      "old" -> nonEmptyText,
      "new" -> nonEmptyText,
      "confirm" -> nonEmptyText
    ) verifying("新しいパスワードと確認用パスワードが一致していません", result => result match {
      case (old,newPass,confirm) => newPass == confirm
    }) verifying("古いパスワードと新しいパスワードが同じです",result => result match {
      case (old,newPass,confirm) => old != newPass
    }) verifying ("パスワードの更新に失敗しました",result => result match {
      case (old,newPass,confirm) if( old != newPass && newPass == confirm) =>
        User.updatePassword(id,old,newPass)
      case (old,newPass,confirm) => false
    })
  )   

これで期待通りの動作をするようになります。
ただこれだと最後のバリデーションがあまりかっこよく無いのが…