5

プレイ中のフォームを定義しようとしています!2.0.4次のプロパティと制約があります。

  1. フォームは繰り返される値を処理します(これらの値がタイプであると便利に想定できますnumber)。したがって、これにより、次のようなものになります。

    "numbers" -> list(number)
    
  2. 各番号は一意である必要があります。つまり、送信された他のすべての番号に関して一意である必要があり、データベースにすでに存在する番号に一意である必要があります(これはいくつかの関数で確認できますcheck(num: Int): Boolean)。

  3. フォームエラーは、一意ではない番号に固有である必要があります。「番号が重複しています」という一般的なフォームエラーは発生しません。

行くための最良の方法は何でしょうか?

4

2 に答える 2

3

ここでのコツは、このConstraintのようなカスタム ソートを定義することです。次に、カスタムを で使用して、フォーム内のフィールドをメソッドで検証できます。ConstraintMapping[T]verifying

カスタムには、またはのいずれかConstraintを返すロジックが含まれています。エラー メッセージを結果に渡すことができます。ここで、データベースに重複または存在するものを指定できます。ValidationResultValidInvalidInvalid

カスタム検証のセクションについてはPlay for Scalaを参照してください。

- 制約を作成する

  //Make this lazy to prevent java.lang.ExceptionInInitializerError at runtime.
  lazy val uniqueNumbersConstraint = Constraint[String](Some("Unique numbers constraint"), "")(checkNumbers)

  //"Business Logic". 
  //Important part here is that the function returns a ValidationResult and complies with the signature for Constraint. i.e. f: (T) => ValidationResult
  //Return Valid if n in numbers is not in database and there are no duplicates.   
  //Otherwise return Invalid and an error message showing what numbers are in the database or duplicated. 
  def checkNumbers(numbers: String):ValidationResult  = {
    val splitNums = numbers.split(" ").toList.map(_.toInt)
    val dbnums  = splitNums.partition(database.contains(_))
    if(dbnums._1.isEmpty && uniquesAndDuplicates(splitNums)._2.isEmpty){
      Valid
    }else{
      val duplicates = uniquesAndDuplicates(dbnums._2)._2
      val error = "Database contains: " + dbnums._1 + ", duplicated values: " + duplicates
      Invalid(error)
    }
  }

- カスタム制約を使用してフォームを検証する

  val helloForm = Form(
    tuple(
      "numbers" -> nonEmptyText.verifying(uniqueNumbersConstraint)
    ))

- ユーティリティ

  //Return unique values on left side and duplicate values on right side
  def uniquesAndDuplicates(numbers: List[Int]):Tuple2[List[Int], List[Int]] = {
    numbers.partition(i => numbers.indexOf (i) == numbers.lastIndexOf(i))
  }

  def checkNum(num: Int) = {
    database.contains(num) 
  }

  val database = List(5,6,7)

- など

numbersフォームで a として定義したことに注意してくださいString。私がそれを定義したとき、list(number)それは に評価され続けましたList()。それは拘束力のある問題だと思います。動作する場合List(1,2,3)の代わりに使用するのはかなり簡単な変更です。"1 2 3"list(number)

- サンプル

ここに画像の説明を入力 ここに画像の説明を入力 ここに画像の説明を入力

于 2012-11-21T07:54:56.997 に答える
2

次のようなものはどうですか:

def validateUnique(input: List[Int]): ValidationResult = {

  // Assuming check return true if the input num doesn't exist yet
  def check(num: Int): Boolean = num % 2 == 0
  val unique = input.toSet
  val dbDuplicates = unique.filterNot(check)
  val formDuplicates = input.diff(unique.toSeq)
  val duplicates = (dbDuplicates ++ formDuplicates).toList

  duplicates match {
    case List() => Valid
    case _ => Invalid("Duplicates: " + duplicates.mkString(", "))
  }
}

val uniqueConstraint = Constraint[List[Int]](validateUnique(_))

そして、新しい制約を次のように使用できます。

mapping(
  ...,
  "ints" -> list(number).verifying(uniqueConstraint)
  ...
于 2012-11-20T10:21:14.417 に答える