在这个问题:If a form field has multi validators, how to let play verify them one by one, not all?中,Julien给了我一个名为stopOnFirstFail
的方法来解决我的问题:
def stopOnFirstFail[T](constraints: Constraint[T]*) = Constraint { field: T =>
constraints.toList dropWhile (_(field) == Valid) match {
case Nil => Valid
case constraint :: _ => constraint(field)
}
}
它的用法是:
val loginForm = Form(
"name" -> (text verifying stopOnFirstFail( nonEmpty, minLength(4) ))
)
但我希望定义一个可以用作:
的dslval loginForm = Form(
"name" -> (text verifying ( nonEmpty or minLength(4) ))
)
我尝试为play.api.data.validation.Constraint
定义隐式方法:
import play.api.data.validation._
implicit def _Constraint[T](cons: Constraint[T]) = new {
def or[T](other: Constraint[T]) = Constraint { field: T =>
cons(field) match { // (!)
case Valid => other(field)
case invalid => invlaid
}
}
}
但它无法编译,(!)行中的错误和消息是:
type mismatch;
found: field.type (with underlying type T) required: T
Note: implicit method _Constraint is not applicable here
because it comes after the application point and it lacks an explicit result type
如何解决?
答案 0 :(得分:3)
or
方法不接受类型参数:
implicit def toLazyOr[T](cons: Constraint[T]) = new {
def or(other: Constraint[T]) = Constraint { field: T =>
cons(field) match {
case Valid => other(field)
case Invalid => Invalid
}
}
}
答案 1 :(得分:0)
def stopOnFirstFail[T](constraints: Constraint[T]*) = Constraint { field: T =>
var result: ValidationResult = null
val loop = new Breaks
loop.breakable(
for (constrain <- constraints) {
result = constrain(field)
if (result != Valid) {
loop.break()
}
}
)
if (result == null) Valid else result
}
此实现只进行一次验证:)