RUBY: преобразование параметров адресной строки URL в хэш

Поискав в интернете способ распарсивания командной строки, решил таки пополнить список самодельщиков и любителей парсеров. Возможно кому-нибудь пригодится данный код.

Итак, задача стояла следующая: необходимо распарсить набор параметров адресной строки URL, с возможностью получать массивы. Поискав в интернете решение этой задачи, решил, что будет быстрее сделать самому то, что нужно.

  def params_to_hash(_params="")
    return {} if _params.grep(/\=/).blank?
    result = {}  
    _params = (URI.parse(_params).query || "") unless _params.grep(/\?/).blank?
    
    l = lambda {|x, a| a[0]=="" ? (a[1].is_a?(Array) ? (x = x || []) << l.call(x, a[1]) : CGI.unescape(a[1])) : (x = x || {}).merge({a[0].to_sym => a[1].is_a?(Array) ? l.call(x[a[0].to_sym], a[1]) : CGI.unescape(a[1])}) }

    _params.split("&").each do |item|
      next if item.size == 0
      item += " " if item.split(/\=/).size < 2
      k = item.split(/\]\[|\[|\]|\=/).reverse
      k[0] = "" if k[0] == " "
      q = k.inject(nil) {|r, i| r = (r.nil? ? i : [i, r]) }
      result = l.call(result, q)
    end
    
    return result
  end

Основную итерацию разборки параметра можно поделить условно на две части.

Подготовка строки параметра для рекурсивной обработки. Например, параметр вида «g[b][e][]=2» преобразуется в массив основным свойством которого является вложенность массивов размерность которых не превышает два элемента «[»g«, [»b«, [»e«, [»«, [»«, „2“]]]]]». Пустые строки в данном наборе расцениваются как признак массива «[]» и знак равно «=».

Пример подготовки массива для параметра с конечным значением типа массив «[]»

>> k = "g[b][e][]=2".split(/\]\[|\[|\]|\=/).reverse
=> ["2", "", "", "e", "b", "g"]
>> q = k.inject(nil) {|r, i| r = (r.nil? ? i : [i, r]) }
=> ["g", ["b", ["e", ["", ["", "2"]]]]]

Пример подготовки массива для параметра с конечным значением типа строка или число «…»

>> k = "g[b][e]=2".split(/\]\[|\[|\]|\=/).reverse
=> ["2", "", "e", "b", "g"]
>> q = k.inject(nil) {|r, i| r = (r.nil? ? i : [i, r]) }
=> ["g", ["b", ["e", ["", "2"]]]]

Последующая обработка массива выполняется рекуррентной лямбда-функцией. В качестве параметров эта функция принимает частично заполненный хэш параметров и массив. Лямбда функция дополняет или создает заново во входном хэше параметр на основе цепочки заложенной в массиве. Полагаю, глядя на массив, несложно будет понять, как работает лямбда функция.

Данная функция парсирует параметры вида «g[b][e][]=1&g[b][e][]=2&g[b][e][]=34&g[b][c]=d», но, увы, она не расчитана для парсирования массива сложных объектов, например, «g[][b][e][]=expression». Массив для этой функции может быть только конечным значением.

Пример работы функции

>> h = "g[b][e][]=1&g[b][e][]=2&g[b][e][]=34&g[b][c]=d"
=> "g[b][e][]=1&g[b][e][]=2&g[b][e][]=34&g[b][c]=d"
>> params_to_hash(h)
=> {:g=>{:b=>{:c=>"d", :e=>["1", "2", "34"]}}}

Любителям dry-кода предлагаю вносить поправки 🙂

Рейтинг
( Пока оценок нет )
Загрузка ...