Dynamically Creating Class and Instance Methods in Ruby
Ruby’s support for dynamically adding methods to existing classes is very powerful and can be used to create seemingly magic results. Unsurprisingly, Rails uses it extensively and you will also find it in the guts of many an acts_as_xxx plugin. Implementing code that adds methods on the fly can be confusing, though. Consider this example:
class ExtendMe
def self.extend_it
class_eval "def added_by_class_eval; end"
instance_eval "def added_by_instance_eval; end"
end
end
ExtendMe.extend_it
Calling ExtendMe.extend_it injects two new methods into the class in slightly different ways. Fair enough. But, what type of method does each end up being?
Let’s find out. First, we’ll check for class methods:
>> ExtendMe.respond_to? :added_by_class_eval
=> false
>> ExtendMe.respond_to? :added_by_instance_eval
=> true
And now for instance methods:
>> em = ExtendMe.new
=> #<ExtendMe:0x35d5a4>
>> em.respond_to? :added_by_class_eval
=> true
>> em.respond_to? :added_by_instance_eval
=> false
Is that what you expected?
When executed in a class method, using class_eval to define a new method creates an instance method. Using instance_eval creates a class method.
I’ll explore why this is so in a future post. For now, just remember that it’s backwards from what you might expect.

Comments