Mr eel

Dynamically Creating Classes

Here’s some interesting metaprogramming trix for generating classes at run-time. This is something I had to do recently, so I thought it would worthwhile writing them down — and yes I really did have a good reason for doing this, I swears.

So the first thing to note, is the the Class object actually has a #new method. This just creates a new class which you can then assign to a variable.


new_class = Class.new

A class isn’t so useful without methods, so you can pass a block to the new method which will act as the body for the class definition.


new_class = Class.new do
  def cry!
    "waaaagh!"
  end
end

new_class.new.cry! #=> "waaaagh!"

It’s a regular class so you can do everything you usually would — subclass, instantiate, mix-in modules etc. Still, it’s not very nice having a class reference inside a regular variable, what you really want is to stick it in a constant. Seems easy enough, but remember we’re talking about doing this at run-time, so the code you’re calling will be inside a method. You cannot assign values to a constant inside a method. Oops. Luckily there is a way around it.

An evil little method called Object#const_set. So, if we define a class like this:


class NeedsToBeMoreDynamic
  def self.make_a_class!
    const_set("NeedsToBeMoreDynamic::KaPow", Class.new)
  end
end

NeedsToBeMoreDynamic.make_a_class! #=> NeedsToBeMoreDynamic::KaPow

Right, that seems dead easy, but there is one caveat and it’s a big one, so be careful for $DEITY’s sake — #const_set will actually hijack an existing constant. That means if you’re not careful you’ll make things screwy. You can actually overwrite references to class definitions. That’s bad… obviously.

Don’t let that put you off though, this is definitely a handy technique to know.

Posted on October 28th, 2008 | There are 0 comments

Comments

Add a comment

All contents © 2005—2007 Luke Matthew Sutton