这里的技巧是定义一个自定义的Constraint,类似于example。然后可以在Mapping[T] 上使用自定义Constraint 来使用verifying 方法验证表单中的字段。
自定义Constraint 包含返回ValidationResult 的逻辑,即Valid 或Invalid。可以将错误消息传递给 Invalid 结果,您可以在其中指定数据库中重复或存在的内容。
有关自定义验证的部分,请参阅 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 定义为String。当我将其定义为list(number) 时,它一直评估为List()。我认为这是一个有约束力的问题。如果使用 list(number) 有效,则使用 List(1,2,3) 而不是 "1 2 3" 是一个相当简单的更改。
- 样本