technology from back to front

King Kong! Misadventures in Ruby meta-programming

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()
     "x"
 end
end

describe "King Kong" do

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

     class X
         def x()
             "not x"
         end
     end

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

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 primate\nHe has eaten your class!"
          Object.send(:remove_const, self.name)
       else
                @@method_history[self][method_name] = true
      end
 end
end

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.

by
tim
on
16/11/11
  1. Frank Shearar
    on 17/11/11 at 1:48 pm

    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 x.class.new. Of course, once those instances fall out of scope, the definition will be eaten by the garbage collector.

  2. Ben Hood
    on 20/11/11 at 10:02 pm

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

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

 
 


eight + = 14

2000-14 LShift Ltd, 1st Floor, Hoxton Point, 6 Rufus Street, London, N1 6PE, UK+44 (0)20 7729 7060   Contact us