How to write more readable url strings that have parameters in Ruby

On my current project, we are using many queries to Solr in the form of a url. In some instances, this could mean unreadable and confusing and I’m-not-even-going-to-try-to-change-this url strings. For example, we could have something like (and this is an easier version of urls we use!):

number_of_rows = 10

url = "http://path.to.my.solr.instance.com/solr?q=(!field_1:* AND !field_2:* AND !field_3:\"VALUE1\" AND !field_4:\"VALUE2\")&rows=#{number_of_rows}&fl=field_5&wt=json&indent=true"

uri = URI.encode url

I personally find it hard to read, and change. Not to mention that this line runs really long—you’d have to scroll to the right to get all of it. And notice how we also have to call URI.encode on the url to uri encode special characters. What if I told you that it can be better?

The answer to this problem is transforming the query parameters in your url to a hash, like so:

number_of_rows = 10

url_path = "http://path.to.my.solr.instance.com/solr"
url_parameters = {
     "q" => "(!field_1:* AND !field_2:* AND !field_3:\"VALUE1\" AND !field_4:\"VALUE2\")",
     "rows" => number_of_rows,
     "fl" => "field_5",
     "wt" => "json",
     "indent" => "true"
}

uri = "#{url_path}?#{url_parameters.to_query}"

Now you can clearly see the url path, as well as each parameter clearly. Also note how number_of_rows doesn’t have to be interpolated anymore, allowing your text editor to highlight the fact that it’s a variable. By creating a parameter hash and calling .to_query on it, you get another bonus: the uri encoding. Pretty cool stuff!

Note that .to_query method is only available within Rails. You can have the same functionality, though, if you are writing Ruby without Rails by making use of Rack::Utils:

require "rack/utils"

number_of_rows = 10

url_path = "http://path.to.my.solr.instance.com/solr"
url_parameters = {
     "q" => "(!field_1:* AND !field_2:* AND !field_3:\"VALUE1\" AND !field_4:\"VALUE2\")",
     "rows" => number_of_rows,
     "fl" => "field_5",
     "wt" => "json",
     "indent" => "true"
}
uri = "#{url_path}?#{Rack::Utils.build_query url_parameters}" 

And there you have it, folks: much more readable and editable url strings.