Маршруты с дополнительным параметром - Play 2.1 Scala - программирование
Подтвердить что ты не робот

Маршруты с дополнительным параметром - 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 сейчас кажется нецелесообразной, поэтому я, вероятно, придерживаюсь двух методов.

4b9b3361

Ответ 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