2016-03-30 8 views
2

(コール):backToを想定しPlayでは、カスタムクエリパラメータを逆引きURLに含めるにはどうすればよいですか?以下のようなルートで

def view (id: String) = Action {r => 
    val backTo = r.getQueryString("backTo") // read custom param 
    ... 
} 

はIオプションのクエリ文字列パラメータです:コントローラで

GET /users/:id controllers.Users.view(id) 

を、私はこのようなカスタムbackToクエリ文字列のparamを読むことができますルート定義に含めたくない(すべてのアクションがそれを読むことができるかもしれない)。

backToパラメータを含むリバースルーティングを使用してURLを作成するにはどうすればよいですか。

routes.Users.view(id).withQueryString("backTo" -> Seq("previous")) 

しかし、それは存在しません:

私のような何かを期待します。

答えて

2

私はちょうどURLを解析して、余分なパラメータでURLを再構築しCallwithQueryString方法売春終わった:

implicit class CallOps (c: Call) { 
    import org.jboss.netty.handler.codec.http.{QueryStringDecoder, QueryStringEncoder} 
    import scala.collection.JavaConverters._ 

    def withQueryString(query: (String,Seq[String])*): Call = { 
    val decoded = new QueryStringDecoder(c.url) 
    val newUrl = new QueryStringEncoder(decoded.getPath) 
    val params = decoded.getParameters.asScala.mapValues(_.asScala.toSeq).toSeq 
    for { 
     (key, values) <- params ++ query 
     value <- values 
    } newUrl.addParam(key, value) 
    Call(c.method, newUrl.toString, c.fragment) 
    } 
} 

をそして今、私はこのようにそれを使用することができます:

routes.Users.view(id).withQueryString("backTo" -> Seq("previous")).url 

URLを再解析する必要はありませんでしたが、Callの時間までにURLは既に構築されています。

1

私はあなたがStringレベルに来なければならないと思うのですが、本当にそのような方法はまだありません(まだ)。

リバースルータが提供しているものは、実際にはplay.api.mvc.Callオブジェクトです。現在のページのソースを見てとることができます。

https://github.com/playframework/playframework/blob/2.5.0/framework/src/play/src/main/scala/play/api/mvc/Http.scala#L359

あなたがabsoluteURL()を得ることができることがわかります - あなたStringを返す - ここからあなたのクエリパラメータを追加することによって、それを操作する必要があります。

(自分でそれを手動で解決せず) Parameters with default valuesを使用してについて間違って何

val url = routes.Users.view(id).absoluteURL() + "?backTo=home"

+0

残念ながら、これはURLを再解析する必要があります。なぜなら、「id」パラメータがパスパラメータ(実装の詳細)であるという前提をできないからです。 "/ users?id = 24?backTo = home" –

+0

@AlvaroCarrascoあなたがルートの正しい順序を保つならば( 'GET/users ...'最初の 'GET /ユーザは:/ id ... '後で)二重疑問符は、とにかく、有効なルーティング構文を使用して発生しませんIMHOはまだずっと安全です – biesior

+0

@biesior私のポイントは、逆ルーティングが実際の実装を心配する必要はないルート。単一のルートを 'path param'から' query param'を使用するように変更すると、自動的に無効なURLが生成されることはありません。 –

1

?サンプル:

def view(id: String, backTo: String, forwardTo: String, whatever: String) = Action { 
    Ok(
    "ID: " + id 
     + ", backTo: " + backTo 
     + ", forwardTo: " + forwardTo 
     + ", whatever: " + whatever 
) 
} 

ルート:注文のparamsによって

// /users/john-doe 
routes.Users.view("john-doe") 

// /users/john-doe?backTo=prev&forwardTo=next&whatever=bar 
routes.Users.view("john-doe", "prev", "next", "bar") 

GET /users/:id controllers.Users.view(id, backTo ?= null, forwardTo ?= null, whatever ?= null) 

それはあなたが必要なのparamとしてだけでIDと逆のルートを作ることができます

または指定のオプションのパラメータでのみ指定します。

// /users/john-doe?whatever=baz 
routes.Users.view("john-doe", whatever = "baz") 

さらに重要なのは、Playのルーティング構文の下で、手動で操作する必要がないため、タイプセーフです。また、?または&のcharでパラメータを開始する必要があるかどうか気にする必要はありません:"?backTo=home""&backTo=home" ...

+1

ルートファイルに使用することはできませんすべてのページで(あまりにも多くの繰り返し)。 '.withFragment(...) 'メソッドと同じように' Call'に '.withQueryString(...)'メソッドがあると思います。おそらく、値( 'r.getQueryString(...)')を読み込む方法があれば、それを置く方法があるでしょうか? –

+0

あまりにも多くの繰り返し_、説明できますか? 'routes.Users.view(" john-doe "、whatever =" baz ")の文法ではありません。 – biesior

+0

私は40のルートを持っていますが、それらのすべてが潜在的にオプションの 'backTo'パラメータを取る可能性があるので、その1つ1つ(ルート定義では、繰り返しがある場所)にそのパラメータを入れなければなりません。 –

関連する問題