Маршруты с дополнительным параметром - Play 2.1 Scala
Итак, в Play 2.0 у меня было это:
GET /tasks/add controllers.Tasks.addTask(parentId: Option[Long] = None)
GET /tasks/:parentId/add controllers.Tasks.addTask(parentId: Option[Long])
С помощью такого метода контроллера:
def addTask(parentId: Option[Long]) = Action {
Ok(views.html.addTask(taskForm, parentId))
}
И он работал. Когда я перешел на 2.1, он, похоже, жалуется на следующие строки: No URL path binder found for type Option[Long]. Try to implement an implicit PathBindable for this type.
В основном, я пытаюсь выполнить ссылку tasks/add
и route tasks/123/add
на тот же метод, который принимает Optional[Long]
. есть идеи как это сделать? Спасибо.
Итак, я получил своего рода не ошибку, это ответ функции на Lighthouse: "Мы удалили поддержку Option [Long] в связующих элементах пути, поскольку нет смысла иметь необязательный параметр пути. реализуйте свой собственный путь, который поддерживает его, если хотите". Пока у меня есть 2 решения, передающих -1 в качестве parentId, что мне действительно не нравится. Или имеет 2 разных метода, которые, вероятно, имеют больше смысла в этом случае. Реализация PathBindable сейчас кажется нецелесообразной, поэтому я, вероятно, придерживаюсь двух методов.
Ответы
Ответ 1
Play 2.0 поддерживает Option
в параметрах пути, Play 2.1 больше не поддерживает это, они удалили PathBindable для опции.
Одно из возможных решений:
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 ""
}
}
И добавьте это в Build.scala
, используя routesImport += "extensions.Binders._"
. Запустите play clean ~run
, и он должен работать. Иногда перезагружается привязка "на лету".
Ответ 2
Я думаю, вы должны добавить знак вопроса:
controllers.Tasks.addTask(parentId: Option[Long] ?= None)
Ответ 3
Из этого routes-with-optional-parameter предложение выглядит следующим образом:
GET / controllers.Application.show(page = "home")
GET /:page controllers.Application.show(page)
Ответ 4
Простое решение вашей проблемы без необходимости передавать значение по умолчанию - это добавить простой прокси-метод, который обертывает параметр в опции.
Маршруты
GET /tasks/add controllers.Tasks.addTask()
GET /tasks/:parentId/add controllers.Tasks.addTaskProxy(parentId: Long)
Контроллер:
def addTask(parentId: Option[Long] = None) = Action {
Ok(views.html.addTask(taskForm, parentId))
}
def addTaskProxy(parentId: Long) = addTask(Some(parentId))
Ответ 5
У меня было то же самое и больше, если вы указали проход как GET/foo:id
и controllers.Application.foo(id : Option[Long] ?= None)
, вы получите сообщение об ошибке It is not allowed to specify a fixed or default value for parameter: 'id' extracted from the path
с другой стороны, которое вы можете сделать следующим образом GET/foo controllers.Application.foo(id : Option[Long] ?= None)
, и он будет работать, ожидая, что ваш запрос выглядит как .../foo?id=1