Advertisement
Here’s a fun snippet cooked up for the Camping 1.3 release due later today, laid out a bit nicer so you can play with it on your own.
Goal is: to parse a query string in as few bytes as possible. And to allow the Hash-like syntax from PHP and Rails.
def qs_parse(qs)
qs.split(/[&;]/n).
inject({}) { |h,p|
k, v = p.split('=',2)
h.merge(
k.split(/[\]\[]+/).reverse.
inject(v) { |x,i| {i=>x} }
){|_,o,n|o.merge(n)}
}
end
Believe me, there’s a real zen in the inner-inject/merge-block routine. Wield it like so:
>> qs_parse("name=Philarp+Tremain&hair=sandy+blonde")
=> {"name"=>"Philarp+Tremain", "hair"=>"sandy+blonde"}
>> qs_parse("post[id]=4&post[nick]=_why&post[message]=GROSS!&a=1")
=> {"a"=>"1", "post"=>{"message"=>"GROSS!", "nick"=>"_why", "id"=>"4"}}
Obviously, in the final version, stuff gets unescaped and all that. This exercise only focuses on parsing the structure. It would be nice for the merge-block to be tail recursive. It only goes one level presently.
Read: Injecting a Hash Backwards and the Merge Block