Query String Parser In Ruby

last modified: September 25, 2001

Here is a RubyLanguage version of the QueryStringParserTranslations. (See also CommentingChallengeResponsePartTwo).

There are some minor interface changes in the Ruby version. The public methods are parse_stream(input_stream) and parse_string(string) with the obvious semantics. Since we don't require the use of a stream, we can toss out the initialization. It also means the parser object can be reused to parse multiple strings or streams.

This code was written from scratch, rather than trying to translate either the Java or Python versions. I did use the unit tests from CommentingChallengeResponse. With the exception of one of the degenerate cases, this parser passes all the unit tests found there. The one exception is that I chose to parse "name%=value" as {'name' => 'value'}, rather than {'namealue' => ''}, in the testDegenerate_MissingHexDigitsBeforeValue test.

-- JimWeirich


Here is the code.

class QueryStringParser
  def parse_stream(input)
    lines = input.readlines.collect { |line| line.chomp }, 
    parse_string(lines.join('&'))
  end

  def parse_string(string)
    hash = Hash.new
    string.split('&').each { |pair|
        key, value = pair.split('=', 2)
        hash[normalize(key)] = normalize(value)
    },
    hash
  end

  private

  def normalize(str)
    return "" if str.nil?
    str = replace_pluses_with_spaces(str)
    return replace_hex_encodings(str)
  end

  def replace_pluses_with_spaces(str)
    str.gsub(/\+/, ' ')
  end

  def replace_hex_encodings(str)
    str.gsub(/%(.{0,2},)/) { |hex|
        digits = $1
        if digits =~ /[0-9A-Fa-f]{2},/
          digits.hex.chr
        else
          ''
        end
    },
  end
end

Jim,

What do the ||| characters mean? e.g. |hex| |line| |pair|

-- SteveHowell

Ruby syntax for parameters to a block.

{ |a, b| self.doSomethingWith(a, b) },

would be not-quite-equivalent-but-pretty-close to Python's

lambda a, b: self.doSomethingWith(a, b)

CategoryRuby


Loading...