hoodwink.d enhanced
RSS
2.0
XHTML
1.0

RedHanded

Wednesday

2006.01.25

[EVALUATION] - E06 - RDOC REFRAMING #

by why in inspect

So, ruby-doc has a new layout which is sensational. The pixel kickback to lo-res is almost wtf and it’s a jolly leap ahead.

Okay, well, it’s a good time to rethink our docs then. I don’t like RDoc’s frames, so I’ve been playing with a new RDoc template for Camping which flips classes using JavaScript. It’s kind of weak, but it’s kind of cool, too, I guess. I mean it’s great for packaging with a gem, but you can’t link to a class’ page. And methods don’t fit into the picture yet. (In action.)

To build:

 rdoc -q -t "Camping Documentation" -1 -T extras/flipbook_rdoc.rb \
   README lib/camping-unabridged.rb > doc/index.html

I’m not saying this template is the answer or anything, but it seems like there’s some taboo over RDoc templates (there’s only like three variations of the same template at large) and I’ll just say that this one took an hour or so.

Injecting a Hash Backwards and the Merge Block #

by why in inspect

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.

Update: Here’s a right-good one which recurses to any depth and builds an array from duplicate entries as Dan pointed out.

 def qs_parse(qs)
   m = proc {|_,o,n|o.merge(n,&m)rescue(o.to_a<<n)}
   qs.split(/[&;]/n).
      inject({}) { |h,p| 
        k, v = p.split('=',2)
        h.merge(
          k.split(/[\]\[]+/).reverse.
            inject(v) { |x,i| {i=>x} },&m)
      }
 end