63

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?

4 Answers 4

77

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

Sign up to request clarification or add additional context in comments.

1 Comment

Seems like it's turning spaces into + not %20 >> {y: "blah blah"}.to_query outputs "y=blah+blah"
76

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>

2 Comments

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".
To give an example of the issue with CGI.escape, a link like link_to("hi", "mailto:[email protected]?body=#{CGI.escape("one two")}") would give you the mail body "one+two" in Apple's desktop Mail.app.
44

ERB::Util.url_encode

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

1 Comment

You need this one if you want spaces to be represented as %20
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?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.