为什么我不能用铲子算子设置uri.query?

Why can't I use the shovel operator to set uri.query?

我正在使用 ruby URI 来构建基本 uri,但我对某些事情感到困惑。

这是我的代码:

uri = URI("https://myhost.com")
uri.path << "/myapi/endpoint"
uri.query = "p1=value1&p2=value2"

uri.to_s
=> "https://myhost.com/myapi/endpoint?p1=value1&p2=value2"

一切都很好,但我不明白为什么我可以使用 << 运算符来设置 uri.path 而不是 uri.query?

例如,以下代码不适用于设置 uri.query

uri = URI("https://myhost.com")
uri.path << "/myapi/endpoint"
uri.query << "p1=value1&p2=value2"

因为传递给构造函数的解析的URL没有查询,所以它是nil,路径被创建为一个空字符串。将查询设置为空字符串将允许这样做。

这只是示例,因为有比铲子操作员更好的设置方法。

irb(main):001:0> require 'uri'
=> true
irb(main):002:0> uri = URI('http://example.com')
=> #<URI::HTTP http://example.com>
irb(main):003:0> uri.path
=> ""
irb(main):004:0> uri.query
=> nil
irb(main):005:0> uri.query = ""
=> ""
irb(main):006:0> uri.query << 'p1=value1&p2=value2'
=> "p1=value1&p2=value2"
irb(main):007:0> uri
=> #<URI::HTTP http://example.com?p1=value1&p2=value2>

更好:

irb(main):011:0> uri.query =+ 'p1=value1&p2=value2'
=> "p1=value1&p2=value2"
irb(main):012:0> uri
=> #<URI::HTTP http://example.com?p1=value1&p2=value2>

因为nil不响应<<,而uri.query默认是nil

uri = URI("https://myhost.com")
# => #<URI::HTTPS https://myhost.com> 
uri.query
# => nil 
nil.respond_to? :<<
# => false
uri.path
# => ""
"".respond_to? :<<
# => true

请注意,uri.path 默认为空字符串。当加入完整的 URI 时,路径实际上变成了 /,这就是为什么在 URL 的末尾有一个尾部斜杠:您在主机服务器上请求根路径。