2013-02-20 14 views
14

を再生する私はこれを持っていたルートだからプレイ2.0で2.1 Scalaの

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.基本的に、私が達成しようとしているのは、Optional[Long]を受け入れる同じ方法に、tasks/add経路とtasks/123/add経路を持つことです。どのようにこれを行うにはどのようなアイデア?ありがとう。

Lighthouseの機能応答は、バグではありません。「オプションのパスパラメータを持たないため、パスバインディングのOption [Long]サポートを削除しました。あなたが好きなら、それをサポートする独自のパスバインディングを実装することができます。これまでのところ、2つの解決策があり、-1をparentIdとして渡しています。私はそれが本当に好きではありません。または、2つの異なる方法があります。この場合、おそらくもっと意味があります。 PathBindableを実装することは現時点では実現可能ではないようですので、おそらく2つの方法があると思います。

答えて

13

はもはや2.1を再生、パスパラメータでOptionをサポート2.0を再生しませんこれをサポートし、Option for 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 "" 
    } 
} 

そしてroutesImport += "extensions.Binders._"を使用してBuild.scalaにこれを追加します。実行play clean ~runと動作するはずです。フライでバインダーをリロードすることはときどきしか動作しません。

+0

ありがとう、私はそれを報告した。あなたはバグ修正を待つことなく、望ましい動作を得る方法を知っていますか? – Laky

+2

Ok:パスバインディングのOption [Long]サポートを削除しました。オプションのパスパラメータを持つのは意味がありません。しかし、任意の値の代わりにOptionalを渡すことは、私にとってはずっとうれしいようです。私たちが最初に選択肢を持っていた理由はそれですか?たぶん私はこの場合2つの異なるメソッドを作成します。なぜなら-1をidとして渡すよりも理にかなっているからです。 – Laky

+4

はい、そうです、それははるかに優れています。私は彼らの決定を理解していない、なぜ、より良いURLを可能にしていた何かを削除する? –

5

私はあなたが疑問符を追加する必要が思う:提案は次のようになり

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

+2

はありません。 –

+0

@ Marusは良い点を作っていますが、タイトルにある質問に答えたので、とにかく+1します。「オプションのパラメータを持つルート」 –

5

このroutes-with-optional-parameterから:

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

私はこれについて知っていますが、デフォルト値を渡す必要があります。パラメータにはidを含めるか、何も指定しないでください。私は何もない部分を示すために-1などを渡すことができましたが、私にとってはこれがもっと良いと思われるので、Optionを使用する方が好きです。 – Laky

+0

実行時にデフォルトパラメータを計算する場合はどうすればよいですか?デフォルトのパラメータのリテラルとしてはどうすればよいですか? –

+0

私はこのテクニックを働かせることができません。私はhttp 500を取得します。私はPOSTを使用しています。 POST /コピー/:param1 /:param2 @ controllers.MyController.copy(param1、param2) POST /コピー/:param2 @ controllers.MyController.copy(param1 = ""、param2)。投稿リクエストは "/ copy/somestring"です。 – Skychan

0

あなたはGET/foo:idとしてパスを指定した場合、私は同じことなどを持っていたとcontrollers.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

関連する問題