This post originated from an RSS feed registered with Ruby Buzz
by Christopher Cyll.
Original Post: Lessons From Hpricot
Feed Title: Topher Cyll
Feed URL: http://feeds.feedburner.com/cyll
Feed Description: I'm not too worried about it. Ruby and programming languages.
HTML processing, C parser, yada, yada, yada. What lesson did I
actually learn from Hpricot?
Abuse the / operator!
Why, the Lucky Stiff, presents this neat bit of code:
doc = Hpricot.parse(File.read("index.html"))
(doc/:p/:a).each do |link|
p link.attributes
end
Nice! That's hot. Let's run with this for a moment and add /
navigation to hashes.
class Hash
def /(key)
self[key]
end
end
people = {:toph => {:name => "Topher Cyll"}}
people/:toph/:name
==> "Topher Cyll"
Pretty cool, huh? Of course, it's not much more concise than using the
standard indexing operator.
people[:toph][:name]
But the real win for me is how it looks like path syntax (ala XPath or
Unix filenames).
You can also do this for Arrays if you like:
class Array
def /(key)
self[key]
end
end
people = [{:name => "Topher Cyll"}, {:name => "Al Gore"}]
people/1/:name
==> "Al Gore"
Of course, it's even better for things that actually naturally use
path syntax. I imagine you could make a decent XPath syntax for REXML
if you tried. And here's an example of what you could do with the Dir
module.
class Dir
def /(key)
Dir.new("#{path}/#{key}")
end
end
root = Dir.new("/")
root/:Users/:toph
# Strings work to
root/"Users"/"toph"
class Dir
def Dir./(key)
Dir.new("/#{key}")
end
end
# Since we probably would use the filesystem root
# a lot, might as well make the module represent
# the root.
Dir/:Users/:toph
I'm not sure I'd use any of the examples I've listed above in
production code, but still, it's pretty cool stuff. Before I go,
here's something truly horrible, and kind of awesome...
def method_missing(name, *args)
return name
end
people = {:toph => {:name => "Topher Cyll"}}
people/toph/name
==> "Topher Cyll"
By making method_missing return the symbol of the missing method, we
can omit the : before the symbol names. But the love of Ruby... don't
do it!