Post

How to encode an URL String in Ruby

Short answer, encoding a Ruby String

2024 edition is :

1
URI::Parser.new.escape(my_url_string)

There’s already a full stackoverflow question about this, but it seems that from Ruby 3, the only working version (without heavy tweaks) is the one described above.

Full example :

1
2
3
4
5
6
7
8
require 'uri'

my_string = "hello world"
my_url_string = "https://somedomain.com?word=#{my_string}"
URI::Parser.new.escape(my_url_string)

# => "https://somedomain.com?word=hello%20world"

Corner case : unescaped characters

When you try to pass a quote mark however, this doesn’t work :

1
2
3
4
5
6
7
require 'uri'

my_string = "hello?world"
my_url_string = "https://somedomain.com?word=#{my_string}"
URI::Parser.new.escape(my_url_string)

# => "https://somedomain.com?word=hello?world"

This requires a little hack .gsub('?', '%3F')

1
2
3
4
5
6
7
require 'uri'

my_string = "hello?world"
my_url_string = "https://somedomain.com?word=#{my_string.gsub('?', '%3F')}"
URI::Parser.new.escape(my_url_string)

# => "https://somedomain.com?word=hello%253Fworld"

Why the little hack ? Well I didn’t take time to take a deep dive into the escape method, however, I suppose that given the fact that the quote mark is already part of a regular URL (it’s a delimiter for the query string), this character is not encoded.

So let’s push this assumption by trying to encode :// (I left this part as an exercice for you:)

…

Ok they are not encoded. Which leads me to the last paragraph.

Robustness of URL String encoding in Ruby

I tried some other methods, but this one is definitely the one which works right now. I deliberately mentioned the year in the title of the topic, because I’m not fully sure this answer will be still valid in say, 2 or 3 years, but as of now, it’s definitely the most robust way I’ve found (so far).

Apart from characters that actually belong to a regular URL, I didn’t find any other tricky stuff.

Depending on the use case, escaping those characters might be a good or bad idea.

Conclusion

Nothing special in this conclusion, I only hope you have won 5 minutes today because of this article :)

Best,

David.

This post is licensed under CC BY 4.0 by the author.