Skip to content

diasbruno/simple-url

Repository files navigation

Simple URL

ruby's URI is a very simple way to deal with...well, uri.

the problem is the search (query string).

dealing with search string by hand is really annoying and error prune. as the search has no form specified on the RFC, we can play with it, it opens a lot of interesting ideas to providing a better way to manage it.

an example is a search that works with key/values pairs that can contains duplicated keys:

a=ok&a=meh

if this is not a good idea for you application, we could implement a query string that uses a hashmap as storage.

a required interface is:

interface QueryString {
  static QueryString from_string(String query_string);
  String to_s();
}
class HashmapSearch
  def self.from_string(query_string)
    ary = URI.decode_www_form(query_string || '')
    new(ary)
  end

  def initialize(query)
    # if a keys is present many times,
    # the last one will get on the hash.
    @query = query.empty? ? {} : Hash[query]
  end

  def to_s
    URI.encode_www_form(@query)
  end

  # operations is up to you!

  def add(key, value)
    @query[key] = value
  end

  def [](key)
    @query[key]
  end

  def remove(key)
    @query = @query.reject do |pair|
      k, = pair
      k == key
    end
  end
end

getting everything together...

irb> a = SimpleUrl::Url.new('https://okokok.com/path?a=1&a=2', HashmapSearch)
=> #<SimpleUrl::Url:0x00000000017447e8 @url=#<URI::HTTPS https://okokok.com/path?a=1&a=2>, @query_string_class=HashmapSearch, @query=#<HashmapSea...
irb> a.query
=> #<HashmapSearch:0x0000000001744338 @query={"a"=>"2"}>
irb> a.url.path = "/asdf"
=> "/asdf"
irb> a.to_s
=> "https://okokok.com/asdf?a=2"
irb> a.query.add('b', 2)
=> 2
irb> a.to_s
=> "https://okokok.com/path?a=2&b=2"
irb(main):039:0> a.query.add('a', 43)
=> 43
irb(main):040:0> a.to_s
=> "https://okokok.com/path?a=43&b=2"

irb> a = SimpleUrl::Url.new('https://okokok.com/path?a=1&a=2', SimpleUrl::KeyValueQueryString)
=> #<SimpleUrl::Url:0x0000000003c32f78 @url=#<URI::HTTPS https://okokok.com/path?a=1&a=2>, @query_string_class=SimpleUrl::KeyValueQueryString, @q...
irb> a.query.to_s
=> "a=1&a=2"
irb(main):043:0> a.query.add('a', 3)
=> [["a", "1"], ["a", "2"], ["a", 3]]
irb(main):044:0> a.query.to_s
=> "a=1&a=2&a=3"

license

This code is released under Unlicense.

See License