61

If I'm in an RHTML view in Rails, it is easy to URL-escape something:

<a href="/redirect?href=<%=u target %>">Foo</a>

How do I do this in a string? I'd like to do something like this:

<% redirect_href = "/redirect?#{url_escape target}&amp;foo=bar&amp;baz=some_other_stuff" -%>
<a href="<%= redirect_href =>">Foo</a>

This must be trivial, right?

Josh Glover
  • 25,142
  • 27
  • 92
  • 129

4 Answers4

75

Rails (activesupport) defines Hash#to_param (aliased to Hash#to_query):

 {foo: 'asd asdf', bar: '"<#$dfs'}.to_param
 # => "bar=%22%3C%23%24dfs&foo=asd+asdf"

It's worth noting that it sorts query keys (for HTTP caching).

Hash#to_param also accepts optional namespace parameter:

{name: 'David', nationality: 'Danish'}.to_param('user')
# => "user[name]=David&user[nationality]=Danish"

http://api.rubyonrails.org/classes/Hash.html#method-i-to_param

Ernest
  • 8,701
  • 5
  • 40
  • 51
  • 5
    Seems like it's turning spaces into `+` not `%20` `>> {y: "blah blah"}.to_query` outputs `"y=blah+blah"` – cdmo May 16 '19 at 12:17
75

CGI.escape will do it:

<% redirect_href = "/redirect?#{CGI.escape target}&amp;foo=bar&amp;baz=some_other_stuff" -%>
<a href="<%= redirect_href =>">Foo</a>
Tom Harrison
  • 13,533
  • 3
  • 49
  • 77
Josh Glover
  • 25,142
  • 27
  • 92
  • 129
  • 15
    `CGI.escape` is not the best thing, as it encodes space as '+' which is deprecated and not always parses correctly on the other side. For example, if you have Rails route "/my-path/:query" where query includes '+', it will stay as '+' after route parsing. To make it work better, use `ERB::Util.u(string)`, which escapes space as "%20". – Kaplan Ilya Oct 01 '17 at 09:32
  • 1
    To give an example of the issue with CGI.escape, a link like `link_to("hi", "mailto:foo@bar.com?body=#{CGI.escape("one two")}")` would give you the mail body "one+two" in Apple's desktop Mail.app. – Henrik N Nov 22 '19 at 13:54
43

ERB::Util.url_encode

can be used from anywhere, part of ruby std lib.

Viktor Trón
  • 8,774
  • 4
  • 45
  • 48
11

Use either CGI::escape or ERB::Util.url_encode but not URI.encode.

URI.escape has been deprecated circa Ruby 1.9.2: What's the difference between URI.escape and CGI.escape?

Community
  • 1
  • 1
thekingoftruth
  • 1,711
  • 1
  • 25
  • 24