Hello all,
I started learning Ruby not long ago and I’d really like to understand
concepts behind it.
Poignant Guide to ruby (http://poignantguide.net/ruby/chapter-6.html)
is a very usefull book for this.
Below example is extracted from this book and some things remain quite
magical for me.
The guts of life force within Dwemthy’s Array
class Creature
Get a metaclass for this class
def self.metaclass; class << self; self; end; end
Advanced metaprogramming code for nice, clean traits
def self.traits( *arr )
return @traits if arr.empty?
# 1. Set up accessors for each variable
attr_accessor *arr
# 2. Add a new class method to for each trait.
arr.each do |a|
metaclass.instance_eval do
define_method( a ) do |val|
@traits ||= {}
@traits[a] = val
end
end
end
# 3. For each monster, the `initialize' method
# should use the default number for each trait.
class_eval do
define_method( :initialize ) do
self.class.traits.each do |k,v|
instance_variable_set("@#{k}", v)
end
end
end
end
class Creature
traits :life, :strength, :charisma, :weapon
end
--------- generated Creature class ----------
class Creature
1. set up reader and writer methods
attr_accessor :life, :strength, :charisma, :weapon
2. add new class methods to use in creature
def self.life( val )
@traits ||= {}
@traits[‘life’] = val
end
def self.strength( val )
@traits ||= {}
@traits[‘strength’] = val
end
def self.charisma( val )
@traits ||= {}
@traits[‘charisma’] = val
end
def self.weapon( val )
@traits ||= {}
@traits[‘weapon’] = val
end
3. initialize sets the default points for
each trait
def initialize
self.class.traits.each do |k,v|
instance_variable_set(“@#{k}”, v)
end
end
end
The thing I do not really understand is the instance_eval and
class_eval in the self.traits method.
It seems that metaclass.instance_eval define_method create a Class
method in the Creature class. Creating a method in the singleton class
of a Class class always define a Class method? can the Singleton class
can also be used to create an instance method of Creature ? Is the way
presented in this example is what is commonly done to dynamically
define Class and instance method of a Class or are there any other
possible syntaxes ?
The self.traits method also define accessors methods: attr_accessor
*arr, how come this is not done within a define_method statement?
Well… I hope I am not getting to confusing…
I would really appreciate your help as I’d really like to understand
how that’s working.
I have already read several article on metaprogramming but some things
remain quite obscure to me
Thanks a lot,
Luc