So in Play 2.0 I had this:
GET /tasks/add controllers.Tasks.addTask(parentId: Option[Long] = None)
GET /tasks/:parentId/add controlle
Play 2.0 supported Option
in path parameters, Play 2.1 no longer supports this, they removed the PathBindable for Option.
One possible solution would be:
package extensions
import play.api.mvc._
object Binders {
implicit def OptionBindable[T : PathBindable] = new PathBindable[Option[T]] {
def bind(key: String, value: String): Either[String, Option[T]] =
implicitly[PathBindable[T]].
bind(key, value).
fold(
left => Left(left),
right => Right(Some(right))
)
def unbind(key: String, value: Option[T]): String = value map (_.toString) getOrElse ""
}
}
And add this to Build.scala
using routesImport += "extensions.Binders._"
. Run play clean ~run
and it should work. Reloading the Binders on the fly only sometimes works.
I had the same thing and more if you specify the pass as GET/foo:id
and controllers.Application.foo(id : Option[Long] ?= None)
you get an error It is not allowed to specify a fixed or default value for parameter: 'id' extracted from the path
on the other side you can do as follows GET/foo controllers.Application.foo(id : Option[Long] ?= None)
and it will work expecting that your request looks like as .../foo?id=1
I think you have to add a question mark:
controllers.Tasks.addTask(parentId: Option[Long] ?= None)
From this routes-with-optional-parameter the suggestion goes like:
GET / controllers.Application.show(page = "home")
GET /:page controllers.Application.show(page)
The simple solution to your problem, without having to pass a default value, is to add a simple proxy method that wraps the parameter in an option.
Routes:
GET /tasks/add controllers.Tasks.addTask()
GET /tasks/:parentId/add controllers.Tasks.addTaskProxy(parentId: Long)
Controller:
def addTask(parentId: Option[Long] = None) = Action {
Ok(views.html.addTask(taskForm, parentId))
}
def addTaskProxy(parentId: Long) = addTask(Some(parentId))