Skip to content

Instantly share code, notes, and snippets.

@sam
Last active December 18, 2015 16:09
Show Gist options
  • Save sam/5809282 to your computer and use it in GitHub Desktop.
Save sam/5809282 to your computer and use it in GitHub Desktop.
Get rid of Async wrappers in Play Framework Actions. The advantage of this approach over pattern-matching is that it's extensible by downstream code introducing new types, and moves what would otherwise be a runtime error (bad match) to a compiler error (no evidence found).
import play.api.mvc._
import play.api.mvc.{Action => PlayAction}
import scala.concurrent._
object Application extends Controller {
// Define the Type Class that will allow us to coerce our action return-types to Results.
trait RequestHandlerLike[-T] {
def apply(result: T): Result // = result
}
object RequestHandlerLike {
implicit object DefaultRequestHandlerLike extends RequestHandlerLike[Result] {
def apply(result: Result) = result
}
implicit object AsyncRequestHandlerLike extends RequestHandlerLike[Future[Result]] {
def apply(result: Future[Result]) = Results.Async(result)
}
}
// Define our custom Action method.
def Action[A,B](bp: BodyParser[A])
(f: Request[A] => B)
(implicit handler: RequestHandlerLike[B]): PlayAction[A] = PlayAction(bp) { request =>
handler(f(request))
}
// Here's an alias for AnyContent body parsers.
// We're using Context Bounds here instead of an implicit since we don't need to actually
// use the RequestHandlerLike in this version, but we'd still like a compiler error
// if we can't find an evidence parameter for B.
def Action[B:RequestHandlerLike](f: Request[AnyContent] => B): PlayAction[AnyContent] =
Action(parse.anyContent)(f)
// Your standard Action, whose body returns a Result.
def index = Action {
Ok("Hello World!")
}
// If you return a Future[Result] it still works, and no need to wrap it with Async!
def showMeTheMoney = Action {
future { "Hello Future World!" }.map(Ok(_))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment