Skip to content

Instantly share code, notes, and snippets.

@guersam
Last active October 6, 2015 17:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save guersam/0cfd0d9212fa6d605597 to your computer and use it in GitHub Desktop.
Save guersam/0cfd0d9212fa6d605597 to your computer and use it in GitHub Desktop.
Generic QueryStringBindable for Play 2.4
// ...
// add this in settings
play.sbt.routes.RoutesKeys.routesImport += "util.GenericQueryStringBindable._"
package util
import play.api.mvc.QueryStringBindable
import shapeless._
import shapeless.labelled.{ FieldType, field }
trait GenericQueryStringBindable {
implicit def hNilBindable: QueryStringBindable[HNil] =
new QueryStringBindable[HNil] {
def bind(key: String, params: Map[String, Seq[String]]): Option[Either[String, HNil]] =
Some(Right(HNil))
def unbind(key: String, value: HNil): String = ""
}
implicit def hlistBindable[K <: Symbol, H, T <: HList](implicit
fieldKey: Witness.Aux[K],
headBindable: QueryStringBindable[H],
tailBindable: Lazy[QueryStringBindable[T]]
): QueryStringBindable[FieldType[K, H] :: T] =
new QueryStringBindable[FieldType[K, H] :: T] {
private val fieldName = fieldKey.value.name
def bind(key: String, params: Map[String, Seq[String]]): Option[Either[String, FieldType[K, H] :: T]] =
for {
e <- headBindable.bind(s"$key.$fieldName", params)
i <- tailBindable.value.bind(key, params)
} yield for { h <- e.right; t <- i.right } yield field[K](h) :: t
def unbind(key: String, value: FieldType[K, H] :: T): String =
headBindable.unbind(s"$key.$fieldName", value.head) + "&" +
tailBindable.value.unbind(key, value.tail)
}
implicit def caseClassBindable[A, R <: HList](implicit
gen: LabelledGeneric.Aux[A, R],
bindable: Lazy[QueryStringBindable[R]]
): QueryStringBindable[A] =
new QueryStringBindable[A] {
def bind(key: String, params: Map[String, Seq[String]]): Option[Either[String, A]] =
bindable.value.bind(key, params).map(_.right.map(gen.from))
def unbind(key: String, value: A): String =
bindable.value.unbind(key, gen.to(value))
}
}
object GenericQueryStringBindable extends GenericQueryStringBindable
@guersam
Copy link
Author

guersam commented Oct 6, 2015

unhelpful error message, no coproduct yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment