Search code examples
rubyurinet-http

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


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"

Solution

  • 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>