http://rubyist.g.hatena.ne.jp/edvakf/20090226/1235672230でいけるかと思いつつ少々不安だったので実際に比べてみたらやっぱり違っていた。
結果から言うと
require 'URI'
string = 'str'
p URI.escape(string,/[^-_.!~*'()a-zA-Z\d]/u)
でいける。
上のリンクだと@とか?とかエスケープできていないっぽい。あと、/nじゃなくて/uじゃないとUTF-8をエスケープできない。
warning: regexp match /.../n against to UTF-8 string
みたいなwarningが出る。これについてはここに載ってるからShiftJISとかEUC-JP使ってる人は参考にしてほしい。