26

我在 Rails 应用程序中有一个非常简单的问题,我找不到一个优雅的解决方案。

我有一个类似的网址: http ://www.example.com/some-path/?foo=123&baz=456

我想处理其中一个参数并重定向到: http ://www.example.com/some-path/?baz=456

我希望这通常适用于任何带有参数“foo”的 URL,所以我不想在重写代码中指定“baz”。

我想要的是这样的:

redirect_to request.path, :params => request.query_parameters.except(:foo)

除了那不太行。我知道我可以手动正则表达式或解析查询字符串,但我认为有更好的方法。

4

4 回答 4

35

到目前为止我发现的最好方法是使用:

url_for(params.except(:obsolete_param_name))

更新

正如Grosser所提到的,这会在您的应用程序中打开一个安全漏洞,因为攻击者可以将主机作为 url 参数传递并将用户重定向到不同的网站。为了防止这种情况,您可以使用rap1ds的建议并指定只使用路径。

为此,您可以使用像这样的辅助函数:

def secure_path_for(params, *excluded_params)
  url_for(params.except(*excluded_params).merge(only_path: true))
end
于 2013-06-19T13:34:43.893 回答
6

在传递它之前删除 params[:foo] 怎么样。也许是这样的:

params.delete[:foo]
redirect_to request.path, :params => params

它不是很优雅,但它只增加了一行。顺便说一句,Params 是一个辅助方法,它获取 url 的当前参数

于 2012-11-19T19:59:44.237 回答
6

在 Rails 5中,如果您尝试这样做,您将收到未清理的请求参数错误url_for(params.except(:param))

所以我找到了这种方法:

request_url = request.url # eg. http://qwe.com/path?param1=1&param2=2

query_hash = Rack::Utils.parse_query(URI.parse(request_url).query).except('param1')
url = query_hash.empty? ? request.path : "#{request.path}?#{query_hash.to_query}"

puts url #=> /path?my_param2=2

redirect_to url
于 2016-10-13T17:32:37.360 回答
2
uri = URI.parse(request.url)
new_query = uri.query.split("&").reject{|pair|
  k,v = pair.split("=")
  k =~ /^foo\[?/ # reject params named "foo" or "foo[anything"
}.join("&")
# if the new querystring is empty, assign nil instead of "" so we don't
# end up with a solitary question mark at the end of the url.
uri.query = (new_query.empty? ? nil : new_query)
redirect_to uri.to_s

在尝试以“Rails 方式”做事时遇到一些不明显的问题后,我来到了上述解决方案,如果有这样的方式来解决这个问题。例如:

  • Rails 参数解析将自动为使用特殊方括号语法的查询参数实例化数组和散列:?x[a]=1&y[]=2becoming{"x"=>{"a"=>"1"}, "y"=>["2"]}等等,因此使用提供的查询字符串和参数例程的代码在这方面很难处理。因此,通过原始字符串值过滤参数可能很困难。即使是非 rails/rack CGI 模块也会为您提供数组而不是参数值的字符串。
  • railsparams散列包括 GET、POST 和路由参数,例如:action和,:controller因此无论如何您都不能只是重用它来重建查询字符串。
  • 因此,像 url_for 这样的 URL 助手并没有多大帮助。

考虑到这些问题,我发现我无法使用提供的框架功能来获取一个纯粹且不受干扰的查询字符串,从当前请求中按原样复制,这只是简单地删除了一个参数。然而,上面的代码似乎运行良好。

于 2013-09-27T19:40:22.383 回答