Why doesn't decodeURI("a+b") == "a b"?

+ is not considered a space. One workaround is to replace + with %20 and then call decodeURIComponent

Taken from php.js' urldecode:

decodeURIComponent((str+'').replace(/\+/g, '%20'));

From MDC decodeURI:

Does not decode escape sequences that could not have been introduced by encodeURI.

From MDC encodeURI:

Note that encodeURI by itself cannot form proper HTTP GET and POST requests, such as for XMLHTTPRequests, because "&", "+", and "=" are not encoded


You might want to look at URI.encode and URI.decode:

require 'uri'

URI.encode('a + b') # => "a%20+%20b"
URI.decode('a%20+%20b') # => "a + b"

An alternate, that I use a lot, is Addressable::URI:

require 'addressable/uri'
Addressable::URI.encode('a + b') #=> "a%20+%20b"
Addressable::URI.unencode('a%20+%20b') #=> "a + b"