Rails中如何将Hash作为参数传入URL?
你遇到的这个问题很常见——直接把Ruby Hash对象拼到URL里时,Ruby会默认调用它的to_s方法,生成的字符串格式(比如{"type"=>"credit", "status"=>"1", "invoice_type"=>"1"})既不符合URL查询参数的规范,也没法被Rails的参数解析器正确转换成Hash,所以才会只拿到开头的{。
下面给你两种可靠的解决方法,都是让Hash转换成Rails能正确解析的URL参数格式:
方法一:用Rails内置的to_query方法(推荐)
Rails专门提供了Hash#to_query方法来处理这种场景,它能把Hash转换成符合URL规范的查询字符串,还能自动处理命名空间。如果要把整个Hash放到filter参数下,只需要把Hash包进一个外层Hash里再调用to_query:
@filter = { "type" => "credit", "status" => "1", "invoice_type" => "1" } @report_url = "#{url}?#{ { filter: @filter }.to_query }"
这样生成的URL会是类似:http://example.com/your_path?filter[type]=credit&filter[status]=1&filter[invoice_type]=1
这时在控制器里访问params[:filter],就能拿到完整的Hash对象了:{"type"=>"credit", "status"=>"1", "invoice_type"=>"1"}
方法二:用Ruby标准库的URI.encode_www_form
如果不想依赖Rails的方法,也可以用Ruby标准库的URI.encode_www_form,不过需要手动构造嵌套参数的格式:
require 'uri' @filter = { "type" => "credit", "status" => "1", "invoice_type" => "1" } encoded_params = URI.encode_www_form(@filter.map { |key, value| ["filter[#{key}]", value] }) @report_url = "#{url}?#{encoded_params}"
这个方法和上面的效果是一样的,只是需要手动处理参数的命名空间格式。
为什么原来的方法不行?
当你直接拼接#{@filter}时,Ruby会输出Hash的字符串表示,但这个字符串里的大括号、引号等符号在URL中属于特殊字符,没有经过正确编码的话,服务器端的参数解析器无法识别它是一个Hash结构,甚至会因为编码问题导致参数被截断,所以你只能拿到开头的{。
内容的提问来源于stack exchange,提问作者rj487

