How to use imports and implicits in Play Framework's routes file?
Asked Answered
A

2

9

What's the scope for routes file to find implicits like PathBindable or QueryStringBindable?

For custom types, it's trivial to simply define them in companion object like the following:

case class Foo(data: String)
object Foo {
  implicit val pathBinder: PathBindable[Foo] = ???
}

However, for existing types, it's unclear where to declare implicit to be found by routes file since we cannot do any custom import here.

So, What's the scope of implicits for routes file?

Adamski answered 31/12, 2015 at 7:53 Comment(0)
F
14

This doesn't directly answer the question, but it seems relevant...

You can include custom imports in the routes file by adding to the routesImport key in your build.sbt

For example:

import play.PlayImport.PlayKeys._

routesImport += "my.custom.package.Foo._"

That snippet is borrowed from a blog post I wrote a while ago entitled Using Play-Framework's PathBindable

Filagree answered 31/12, 2015 at 8:39 Comment(3)
I knew there would be something like this! Thank you and happy new year :]Adamski
for me to get the routesImport key i had to import play.sbt.routes.RoutesKeys.routesImportHobnail
The blog post that the author mentioned has been moved to here: cjwebb.com/play-framework-path-bindersTowelling
T
8

we had a queryStringBindable that we needed to use and had a similar situation, we found this question which gave us a clue but the answer from colinjwebb is out of date.

Here's our example which goes from a string to an Option[LoginContext].

package controllers

import play.api.mvc.{Action, AnyContent, QueryStringBindable, Request}
...

object BindableLoginContext {

  implicit def queryStringBindable(implicit stringBinder: QueryStringBindable[String]) = new QueryStringBindable[LoginContext] {
    override def bind(key: String, params: Map[String, Seq[String]]): Option[Either[String, LoginContext]] =
      for {
        loginContextString <- stringBinder.bind(key, params)
      } yield {
        loginContextString match {
          case Right(value) if value.toLowerCase == "web" => Right(LoginContexts.Web)
          case Right(value) if value.toLowerCase == "api" => Right(LoginContexts.Api)
          case _ => Left(s"Unable to bind a loginContext from $key")
        }
      }

    override def unbind(key: String, loginContext: LoginContext): String = stringBinder.unbind(key, loginContext.toString)
  }
}

To use it we needed to use the following import:

import play.sbt.routes.RoutesKeys

and then add the object to the Project like this

lazy val microservice = Project(appName, file("."))
  .settings(
    RoutesKeys.routesImport += "controllers.BindableLoginContext._"
  )
Thirteen answered 13/1, 2017 at 14:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.