0

I'm using ruby URI to build a basic uri and I'm confused about something.

Here is my code:

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"

This is all well and good but I don't understand why I can use << operator to set uri.path but not uri.query?

e.g., the follow code does not work for setting uri.query

uri = URI("https://myhost.com")
uri.path << "/myapi/endpoint"
uri.query << "p1=value1&p2=value2"
sanpaco
  • 785
  • 1
  • 14
  • 32

2 Answers2

1

Because the parsed URL passed to the constructor had no query, so it was nil, the path is created as an empty string. Setting query to an empty string will allow this.

This is only for example as there are better ways to set it than the shovel operator.

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>

Better:

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>
Derek Wright
  • 1,452
  • 9
  • 11
  • Thanks for the detailed explanation. This makes sense to me now. I guess I was overlooking the fact that the `<<` operator is used for string concatenation so it makes sense it wouldn't work on `nil`. – sanpaco Apr 25 '17 at 21:43
1

Because nil does not respond to <<, and uri.query is nil by default.

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

Note that uri.path is an empty string by default. When the full URI is joined, the path effectively becomes /, which is why there's a trailing slash at the end of URLs: you're requesting the root path at the host server.

coreyward
  • 77,547
  • 20
  • 137
  • 166