This seems to be intentional. From url.rb, there is the code:
options[:protocol] = normalize_protocol(options)
options[:host] = normalize_host(options)
options[:port] = normalize_port(options)
result << options[:protocol]
result << rewrite_authentication(options)
result << options[:host]
result << ":#{options[:port]}" if options[:port]
result
ends up being the url string you want to build.
Now, normalize_protocol
will return \\
if you set the protocol: false
normalize_port
then looks at options[:protocol]
specifically returning nil
if options[:protocol] == '//'
regardless of whether you included the port in the host
option or specifically give the port
option.
By doing the normalization in this order what you want seems to be impossible from the core code.
I don't know if this is an oversight or if it is deliberate. Maybe it is considered that you cannot have a port without the protocol. In any event it might be worth you raising an issue with Rails.
In the meantime, you could workaround it with a gsub
. Not brilliant but probably better than nothing. Something like:
2.0.0-p247 :002 > tunnels_url(host: "0.0.0.0port", protocol: false).gsub('port',':3000')
=> "//0.0.0.0:3000/tunnels"