2013-02-20 82 views
14

所以在播放2.0我有這樣的:路線可選參數 - 玩2.1斯卡拉

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]相同的方法。任何想法如何做到這一點?謝謝。

好的,所以我得到了一種它並不是bug,它是Lighthouse的一個功能響應:「我們刪除了Path綁定中的Option [Long]支持,因爲它沒有任何意義可選的路徑參數。可以實現你自己的路徑綁定,支持它,如果你願意的話。「到目前爲止,我有兩個解決方案,傳遞-1作爲parentId,我不太喜歡。或者有兩種不同的方法,這在這種情況下可能更有意義。實現PathBindable現在看起來不太可行,所以我可能堅持使用2種方法。

回答

13

播放2.0支持路徑參數Option,播放2.1不再支持這一點,他們刪除了PathBindable for Option。

一個可能的解決辦法是:

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 "" 
    } 
} 

而且使用routesImport += "extensions.Binders._"這增加Build.scala。運行play clean ~run,它應該工作。即時重新加載粘合劑有時會起作用。

+0

謝謝,我已經報道了。你有沒有想法如何得到所需的行爲,而不必等待錯誤修復? – Laky 2013-02-20 17:21:43

+2

好的,所以:「我們刪除了路徑綁定中的Option [Long]支持,因爲它沒有任何可選的路徑參數,您可以實現自己的路徑綁定,只要您願意,它就支持它。但傳遞一個可選的而不是一些任意的值在我看來好多了。這不就是我們首先有選擇權的原因嗎?也許我寧願在這種情況下創建2種不同的方法,因爲它比傳遞-1作爲id更有意義。 – Laky 2013-02-20 17:51:04

+4

是的你是對的,那好多了。但是,我不明白他們的決定,爲什麼要刪除允許更好URL的內容? – 2013-02-20 17:54:11

5

我認爲你必須添加一個問號:

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

+2

不,這只是爲了查詢參數,而不是爲路徑的一部分。 – 2013-02-20 15:46:38

+0

@Marius提供了一個很好的觀點,但無論如何,因爲你回答了標題中給出的問題:「可選參數的路線」 – 2013-05-08 18:22:42

5

從這個routes-with-optional-parameter的建議是這樣:

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

我知道這一點,但是,我想避開傳遞一個默認值。該參數應該包含id,或者不包含任何內容。我可以傳遞-1或類似的東西來表示沒有任何部分,但我更喜歡使用Option,因爲它對我來說似乎更好。 – Laky 2013-02-20 17:14:47

+0

如果我想在運行時計算默認參數,該怎麼辦?我應該用什麼作爲默認參數的文字? – 2014-02-15 04:57:03

+0

我無法使這種技術工作。我得到http 500.我使用POST。 POST/copy /:param1 /:param2 @ controllers.MyController.copy(param1,param2) POST/copy /:param2 @ controllers.MyController.copy(param1 =「」,param2)。正在發送的帖子請求是「/ copy/somestring」 – Skychan 2015-09-17 15:30:18

0

我有同樣的事情,如果你指定通爲GET/foo:idcontrollers.Application.foo(id : Option[Long] ?= None)您在另一邊,你可以做如下GET/foo controllers.Application.foo(id : Option[Long] ?= None),也將努力期待您的請求看起來像爲.../foo?id=1

2
得到一個錯誤 It is not allowed to specify a fixed or default value for parameter: 'id' extracted from the path更多

無需傳遞默認值即可解決問題的簡單方法是添加一個簡單的代理方法,將參數封裝在一個選項中。

路線:

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 2017-02-11 22:21:50