2013-02-20 4 views
14

Так в Play 2.0 Я это:Маршруты с дополнительным параметром - Play 2.1 Scala

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 и маршрут tasks/123/add ссылка на тот же метод, что принимает Optional[Long]. есть идеи как это сделать? Благодарю.

Хорошо, поэтому я получил своего рода не ошибку, это ответ функции на Маяк: «Мы удалили опцию [Long] поддержку в связующих элементах пути, поскольку нет смысла иметь необязательный параметр пути. может реализовать свой собственный путь, который поддерживает его, если хотите ». Пока у меня есть 2 решения, передающих -1 в качестве parentId, что мне действительно не нравится. Или имеет 2 разных метода, которые, вероятно, имеют больше смысла в этом случае. Внедрение PathBindable сейчас кажется нецелесообразным, поэтому я, вероятно, придерживаюсь двух методов.

ответ

13

Play 2.0 поддерживается Option в параметрах пути, Играть 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, и он должен работать. Иногда иногда происходит перегрузка связующих на лету.

+0

Спасибо, я сообщил об этом. Вы не знаете, как получить желаемое поведение, не дожидаясь исправления? – Laky

+2

Итак, «Мы удалили опцию [Long] поддержки в связующих элементах пути, поскольку нет смысла иметь необязательный параметр пути. Вы можете реализовать свой собственный связующий путь, который поддерживает его, если хотите». Но передача Факультативного вместо какого-то произвольного значения мне кажется намного приятнее. Разве это не причина того, что у нас есть альтернативы? Возможно, я предпочел бы создать в этом случае 2 разных метода, поскольку это будет иметь больше смысла, чем передача -1 в качестве id. – Laky

+4

Да, вы правы, это намного лучше. Однако я не понимаю их решения, зачем удалять что-то, что позволяет использовать более удобные URL-адреса? –

5

Я думаю, вы должны добавить знак вопроса:

controllers.Tasks.addTask(parentId: Option[Long] ?= None)

+2

Нет, это только для параметров запроса, а не для участков пути. –

+0

@Marius делает хорошую точку, но +1 во всяком случае, потому что вы ответили на вопрос, заданный в заголовке: «Маршруты с дополнительным параметром» –

5

Из этого routes-with-optional-parameter предложение выглядит:

GET /     controllers.Application.show(page = "home") 
GET /:page    controllers.Application.show(page) 
+4

Я знаю об этом, однако мне бы хотелось, чтобы вам пришлось выполнить значение по умолчанию. Параметр должен содержать либо идентификатор, либо ничего. Я мог бы передать -1 или что-то подобное, чтобы указать часть ничего, но я предпочел бы использовать Option для этого, поскольку мне кажется намного приятнее. – Laky

+0

Что делать, если я хочу рассчитать параметр по умолчанию во время выполнения? Что следует использовать в качестве литерала для параметра по умолчанию? –

+0

Я не могу заставить эту технику работать. Я получаю http 500. Я использую POST. POST/copy /: param1 /: param2 @ controllers.MyController.copy (param1, param2) POST/copy /: param2 @ controllers.MyController.copy (param1 = "", param2). Выполняется пост-запрос «/ copy/somestring» – Skychan

0

Я имел то же самое, и больше, если вы укажете пропуск в 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

2

Простым решением вашей проблемы без необходимости передавать значение по умолчанию является добавление простого прокси-метода, который обертывает параметр в опции.

Маршруты:

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)) 
+0

Обходной путь, все еще противный, я думаю – Sorona

Смежные вопросы