Grokking Idiomatic Dynamic Ruby

I want to use Ruby to implement something very much like Active Record, but I'm a Ruby newbie.  What I most need to understand is dynamic Ruby, from which it's said the language derives much of its power.  So I read and reread the relevant chapters of the Pickaxe book, which are clear enough on the 'how,' but not so much on the 'why.'  That is, the book adequately explains how to use certain dynamic features, but not why and when I would want to use them.  I've also been lurking on why the lucky stiff's blog, which is chock full of clever, dynamic stuff.  I could mostly follow the dynamic bit of why's (poignant) guide to Ruby, but I wasn't truly internalizing it; I was not groking it.

Thinking I'll understand things if I just try it, I've been both studying the Active Record code while simultaneously writing my own.  My hopes were dashed, though, when I discovered this fundamental structure of ActiveRecord::Base.

class Base
  # class methods and variables

  class << self
    # more methods
  end

  # Instance methods and variables
end

My question was, what the hell is this class << self stuff doing in the middle of the Base class?  No worries, a little Googling turned up this very nice explanation on RubyGarden: the Singleton Tutorial.  This is apparently a Ruby idiom for adding class methods to a class without having to type "ClassName." or "self." before each method name like so: Base.whatever or self.whatever.  Things began to gel, but I hadn'tt yet reached full understanding.  Why?  Because my mental picture of the Active Record class hierarchy kept getting fuzzy as I perused the source code.  For instance, inside what I now know to be the singleton class (virtual class, metaclass, eigenclass, people can't seem to decide [I like the name "shadow" class]) of the Base class, I found these four class methods:

      def table_name
        reset_table_name
      end

      def reset_table_name
        name = "#{table_name_prefix}#{undecorated_table_name(class_name_of_active_record_descendant(self))}#{table_name_suffix}"
        set_table_name name
        name
      end
     
      def set_table_name( value=nil, &block )
        define_attr_method :table_name, value, &block
      end
      alias :table_name= :set_table_name

      private    
        def define_attr_method(name, value=nil, &block)
          sing = class << self; self; end
          sing.send :alias_method, "original_#{name}", name
          if value
            # use eval instead of a block to work around a memory leak in dev
            # mode in fcgi
            sing.class_eval "def #{name}; #{value.to_s.inspect}; end"
          else
            sing.send :define_method, name, &block
          end
        end

If the Active Record developer uses the default class-naming style of Active Record (table names are plural, class names are singular, e.g., table name "orders" gives class name "Order"), then the table_name method above will return the name of the associated database table the first time it's called.  But if you trace the call all the way through, it seems as if the define_attr_method is overwriting the table_name method to return the just determined database table name for each subsequent call.  "Ick!" says I, thinking back to programmer school, "self modifying code!"  That can't be right.  I have obviously not yet grokked the idioms of dynamic Ruby.  The question now is, what is this line of code referring to: sing = class << self; self; end ?

There was just one thing to do, trace through the object creation process myself.  So I whipped up the following code that echoes using Active Record, ran it, and now - now - I grok it.  The code was cleaned up and the numerical ordering was added after the scales fell from my eyes.

class Test
  puts "1. Inside base class, but outside any method, object ID is #{self.object_id}"

  def meth
    puts "9. Inside instance method of base class object ID is #{self.object_id}"
  end

  class << self
    puts "2. Inside singleton class of base class, object ID is #{self.object_id}"

    def meth2
      puts "4. Inside class method of base class, object ID is #{self.object_id}"
      sing = class << self; self; end;
      puts "5. Referencing singleton object, object ID is #{sing.object_id}"
    end
  end
end

class Atest < Test
  puts "3. Inside subclass of base class, object ID is #{self.object_id}"
end

puts "Calling base class method directly"
Atest.meth2

puts "6. Outside subclass of base class, Object ID of subclass is #{Atest.object_id}"

class << Atest
  puts "7. Inside singleton class of subclass, Object ID is #{self.object_id}"
end

puts "Creating instance of subclass"
a = Atest.new
puts "8. Object ID of instance object is #{a.object_id}"

puts "Calling instance methods"
a.meth

class << a
  puts "10. Inside singleton class of instance object, Object ID is #{self.object_id}"
end

If you haven't clicked through any of the links above (and you should), the gist of dynamic ruby concerns what are best known as singleton classess.  The essence being that every object in Ruby can have a singleton class dynamically associated with it; a class that inserts itself between the object and its parent class; essentially making itself a superclass of the object and a subclass of the original class.  And it's important to remember that classes are themselves objects in Ruby.  That's an inadequate explanation, so, really, click through those links.

In any event, if you run the above code, it will produce output similar to this (your object IDs will be different):

1. Inside base class, but outside any method, object ID is 441462
2. Inside singleton class of base class, object ID is 441452
3. Inside subclass of base class, object ID is 441432
Calling base class method directly
4. Inside class method of base class, object ID is 441432
5. Referencing singleton object, object ID is 441372
6. Outside subclass of base class, Object ID of subclass is 441432
7. Inside singleton class of subclass, Object ID is 441372
Creating instance of subclass
8. Object ID of instance object is 441152
Calling instance methods
9. Inside instance method of base class object ID is 441152
10. Inside singleton class of instance object, Object ID is 441112


To help crystalize this, study the following illustration.  Singleton classes are blue-green, ordinary classes are gray.

class hierarchyWhen Ruby processes this program it encounters the class Test definition first and creates an object for it in memory (step 1).  It goes on to process the inards of class Base and finds the next bit of runnable code (i.e., not a method definition) to be class << self.  Since no class methods have been defined yet, this idiomatic code causes Ruby to create a singleton (shadow) class for the Test class object in which to store its class methods.  While inisde this singleton object we print out it's object ID and add a class method.

The processor then encounters the class Atest < Test line. This is standard issue subclassing, and causes Ruby to create a new Atest object (step 3).  The Atest.meth2 line is how class methods are called.  When meth2 runs, you'll note that it runs under the auspices of the Atest object, so that when this line is run: sing = class << self; self; end; it creates a singleton object for the Atest class (step 5).  This is a critical component of Active Record, it's what allows, say, a Person object to have a last_name attribute or a Car object to have a model attribute even though both descend from ActiveRecord::Base.  It also means that the earlier Active Record code wasn't overwriting the table_name method, it was overriding it, and that's cool.

Next the code asks the Atest object to tell us about itself (step 6).  And then we create a singleton class for it with this bit of code class << Atest (step 7).  Finally, we create an actual instance of Atest by calling its new method, and ask it to tell us what it is (step 8).  When we call an instance method of object 'a', we can see that we're running as object 'a' (step 9).  And we complete the chain, by creating a singleton class for object 'a' with the line class << a (step 10).

When we're all done, we have a class/object hierrarchy 6 levels deep.  There's the original Test class and its shadow, where all the class methods are stuffed.  A subclass, Atest, that inherits from Test and has its own class methods stuffed in its own shadow class.  And an instance of this subclass that has a shadow class containing methods that are paritcular to it.

Grok it?