Eval-less Metaprogramming #
I often find myself resorting to eval when writing class methods for metaprogramming, simply because define_method hasn’t penetrated my brain basket yet. No more!
Here goes Florian GroBB changing Ruby as I know it—yet again—with his implementation of an eval-less has_many class method:
class Meta
def self.has_many( sym )
ivar = :"@#{ sym }"
define_method( sym.to_sym ) do
new_value = instance_variable_get( ivar ) || []
instance_variable_set( ivar, new_value )
new_value
end
end
end
Even though has_many is a sorta poor name (we’re not talking about databases here), this method acts like an attr method, but the attribute is always an Array.
class Person < Meta attr_accessor :name has_many :friends def initialize( name ); @name = name; end end >> fred = Person.new( "Fred" ) >> joe = Person.new( "Joe" ) >> teagle = Person.new( "T. Eagle" ) >> teagle.friends << fred >> teagle.friends << joe => [#<Person:0x80f3ebc @name="Fred">, #<Person:0x81fd404 @name="Joe">]

