I have a method to replace URL parameters in an URL. It receives url as mandatory parameter and prefix and/or hash as optional parameters. Examples:
url_replace( '/news?b=2', { b: nil } ) # => '/news'
url_replace( '/news?b=2', { b: 3 } ) # => '/news?b=3'
url_replace( '/news?a=b', '/bar' ) # => '/bar?a=b'
url_replace( '/news?a=b&c=d', '/bar', c: nil ) # => '/bar?a=b'
The method:
def url_replace( target, *args )
uri = URI.parse(URI.escape target)
if hash = args.last.kind_of?(Hash) && args.last
query = uri.query ? CGI.parse(uri.query) : {}
hash.each do |k,v|
v ? query[k.to_s] = v.to_s : query.delete(k.to_s)
end
uri.query = query.any? ? query.map{|k,v| "#{CGI.escape k.to_s}=#{CGI.escape Array(v).join}"}.join('&') : nil
end
prefix = args.first.kind_of?(String) && args.first
uri.path = CGI.escape(prefix) if prefix
CGI.unescape(uri.to_s)
end
I would like some refactoring or speed optimizations.
Okay, here's the code I ended up with:
def url_replace( target, *args )
uri = URI.parse(URI::DEFAULT_PARSER.escape target)
uri.path = CGI.escape(args.first) if args.first.kind_of?(String)
if args.last.kind_of?(Hash)
query = uri.query ? CGI.parse(uri.query) : {}
args.last.each{ |k,v| v ? query[k.to_s] = v.to_s : query.delete(k.to_s) }
uri.query = query.any? ? URI.encode_www_form(query) : nil
end
CGI.unescape(uri.to_s)
end
URI.parse
does not like? \$\endgroup\$URI
is correct here, you have to escape it first (like any browser does):URI.parse(URI.escape('кококо'))
. \$\endgroup\$