2

我在我的网络表单上使用了约束,我注意到有几个表单有类似的验证,例如我有几种类型的表单,它们都有开始日期和结束日期。在每种情况下,我都想验证开始日期是否早于结束日期。这是我从表单创建的案例类:

   case class OrderSearchForm(orderId: Option[Int], startDate:Option[Long], endDate:Option[Long])

和我的验证(让我们暂时忽略 .get() ):

  def validateSearchDate = Constraint[OrderSearchForm]{ 
    osf: OrderSearchForm => {
      if (!osf.startDate.isEmpty && !osf.endDate.isEmpty && osf.startDate.get.compareTo(osf.endDate.get) > 0 )
        Invalid("Begin Date is after End Date.")
      else
        Valid
    }
  }

现在,由于我有很多带有开始日期和结束日期的表单,我想重新编写我的验证以使用代表这些表单的所有案例类。我想知道 typeclass 模式是否可以帮助我解决这个问题:

trait TwoDates[T] { 
  def twoDatesTuple(t: T): (Option[Long], Option[Long]) 
}

trait TwoDatesOSF extends TwoDates[OrderSearchForm] { 
  def twoDatesTuple(t: OrderSearchForm) = (t.startDate, t.endDate) 
}

implicit object TwoDatesOSF extends trait TwoDatesOSF

def validateSearchDate = Constraint[TwoDates[_]] { t: TwoDates[_] => ... (as above)}

但申请不起作用:

validateSearchDate(OrderSearchForm(None, None, None))

产量:

错误:类型不匹配;找到:需要 OrderSearchForm:TwoDates[_] betweenDates(osf)

1) 我可以使用类型类编写通用验证吗?如果是这样,我做错了什么?

2)我可以在避免使用超类的同时编写通用验证(即

abstract class TwoDates(start: Option[Long], end:Option[Long])

case class OrderSearchForm(orderId: Option[String], startDate:Option[Long], endDate:Option[Long]) extends TwoDates(startDate, endDate) 

一旦进行了多个验证,这似乎很尴尬)

谢谢!

4

1 回答 1

1

我认为您可以使用结构类型:

private type TwoDates = { def startDate: Option[Date]; def endDate: Option[Date] }

def validateTwoDates = Constraint[TwoDates] { osf: TwoDates =>
if (!osf.startDate.isEmpty && 
    !osf.endDate.isEmpty && 
    osf.startDate.get.compareTo(osf.endDate.get) > 0) {
        Invalid("Begin Date is after End Date.")
    } else Valid
}

case class Something(
   startDate: Option[Date], 
   endDate: Option[Date], 
   name: String)

private val form = Form(mapping(
   "startDate" -> optional(date),
   "endDate" -> optional(date),
   "name" -> text)
(Something.apply)(Something.unapply).verifying(validateTwoDates))
于 2013-02-08T17:26:00.713 回答