Use Ruby’s method_missing to see what happens to an object

Lately I’ve been generating MS Word .docs from text files, with RedCloth and Hpricot (thank you, why, for both of those), and win32ole. It’s been fun, except for the OLE parts: the ruby bridge is great, but the OLE API itself is strange, good documentation is sparse, and things get…flaky, sometimes.

In troubleshooting a bug that turns bold text on and off at the wrong times, I thought “it’d be nice if I could see all the calls that happen to this ‘selection’ object, in order they happen. Maybe I don’t realize I’m turning the ‘bold’ on at the wrong times.” Enter the Echoer:

class Echoer
    def initialize(name)
        @name = name
    end
    def method_missing(method_name, *args)
        puts "#{@name}.#{method_name}: #{args * ', '}"
        Echoer.new("#{@name}.#{method_name}")
    end
end

The Echoer is a stand-in for a regular object. Whenever a method is called on it, it prints its own name, the name of the method called, and the arguments.

def get_me_my_object
    # RealObject.new
    Echoer.new('obj')
end
obj = get_me_my_object
obj.puts 'Hello there'
obj.name = "Puddin'head Wilson"

# prints:
obj.puts: Hello there
obj.name=: Puddin'head Wilson

Each method call returns a new Echoer, whose name is based on its name, and the method name, so you can chain method calls.

obj.next.upcase.match /pattern/

# prints:
obj.next: 
obj.next.upcase: 
obj.next.upcase.match: (?-mix:pattern)

I should probably make Echoer a BlankSlate object, but I haven’t run into a need for it just yet. I could also inspect the method’s arguments with args.map { |arg| arg.inspect }, so you can tell strings and symbols apart.

Back in OLE-land, I replaced all instances of the selection object with Echoer.new('selection'), re-ran my code, and watched the output. I still haven’t found the source of the bug, but at least I know I’m not turning bold on or off when I don’t expect to.

Thanks to Michael Feathers for this idea. He wrote on the Beautiful Code blog about Spelunking Ruby Methods with Pebbles, but it seems O’Reilly took the blog down. All that’s left are the links from sites like reddit…does anyone know if the content is floating around somewhere out there?

Advertisements

3 thoughts on “Use Ruby’s method_missing to see what happens to an object

  1. Sorry Dan, I was thinking of LaTEX when I posted this, which you are not using. I think I need more sleep at night.

    I am going to try my hand at using your method of writing in text and converting to Word. Do you have some techniques you care to pass along?

  2. Thanks Rob! Yes, I’m using Textile.

    One trick I have is a custom tool in Programmer’s Notepad 2 that wraps the selected text in ‘@’, or if the text has a newline, in pre-tags. The ‘@’ is for in-line code, and the pre-tags for code blocks, so I have it triggered by Ctrl+Shift+C.

    I’m considering doing a post on the whole text-to-Word thing at some point: the need, the approach, everything. If there’s any interest, I might even gem the whole thing up. IMHO, it’s a much nicer way to write MS Word .docs. It’s not perfect, but I think it beats Word’s mousing and binary formats.

Comments are closed.