Friday, 15 May 2015

scala - How to share a validation.Constraint across multiple Forms? -



scala - How to share a validation.Constraint across multiple Forms? -

i'm using constraints on web forms , i've noticed several forms have similar validations, instance have several types of form start date , end date. in each case, want validate start date before end date. here's case class i'm creating form:

case class ordersearchform(orderid: option[int], startdate:option[long], enddate:option[long])

and validation (let's ignore .get() now):

def validatesearchdate = constraint[ordersearchform]{ osf: ordersearchform => { if (!osf.startdate.isempty && !osf.enddate.isempty && osf.startdate.get.compareto(osf.enddate.get) > 0 ) invalid("begin date after end date.") else valid } }

now, since have lots of forms start date , end date, i'd re-write validation work of case classes representing these forms. i'm wondering whether typeclass pattern can help me this:

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)}

but applying not work:

validatesearchdate(ordersearchform(none, none, none))

yields:

error: type mismatch; found : ordersearchform required: twodates[_] betweendates(osf)

1) can write generic validations using typeclasses? if so, doing wrong?

2) can write generic validations while avoiding using super-classes (i.e.

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)

which seems awkward 1 time multiple validations in play)

thanks!

i think can utilize structural types:

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 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))

validation scala playframework-2.0 code-reuse typeclass

No comments:

Post a Comment