King Kong! Misadventures in Ruby meta-programming

By: on November 16, 2011

Sometimes after a particularly fraught bug stomping session you make a frivolous offhand remark to a colleague, for example “I will write a macro that converts lisp definitions in prefix form so that arithmetic looks like how it was taught to you in school” or “I won’t let my unit test really be an integration test ever again”. Today after wrestling with Ruby I mentioned a mild dislike for monkey patching as often used in Ruby and the idea for King Kong was born.

If you don’t like monkey patching in Ruby, then King Kong is the solution. He is a very large primate who likes to have his own way. If you define a class and then monkey patch it King Kong will eat it, it will be gone, no longer available for your use. Fortunately King Kong can’t use source code control systems (yet!) so you can correct your error and ponder his subtle ways.

We shall start by writing a spec:

require "rspec"
require "king-kong"

class X
  def x()

describe "King Kong" do

   it "does not allow monkey patching" do
        Object.const_defined?("X").should == true

     class X
         def x()
             "not x"

     Object.const_defined?("X").should == false

Now we define King Kong!

class Class
    @@method_history = {}

   def method_added(method_name)
       @@method_history[self] ||= {}
       if @@method_history[self][method_name] then
         puts "King kong is the top primatenHe has eaten your class!"
                @@method_history[self][method_name] = true

Run the spec, spec passes, job done! This code is licensed as is and probably shouldn’t be run in production, or even your QA environment but you are welcome to run it on your development machine for minimal comedic effect.

King Kong is a fine example of Ruby meta-programming and an excellent addition to your arsenal of offensive programming tools taking a large amount of inspiration from tools like Guantanamo. Marvel at how easy it is to completely annihilate a class from existence in Ruby, if that was Java you would have to give a class loader or something a walloping with a GreasySpannerFactory to achieve the same thing.

Remember sometimes monkey patching is a solution and some times it is the cause of the problem!

If you want to take a more serious approach to this problem you might want to look here.



  1. Frank Shearar says:

    Of course, X is just another object. remove_const removes the association between the class name (:X) and the class definition, and if there’s an extant instance of X (call it x), you could still create more Xs with Of course, once those instances fall out of scope, the definition will be eaten by the garbage collector.

  2. Ben Hood says:

    I rate this post _ (*) of of 10.

    (*) My blog parser saw an eight so it ate this 1 2.

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>