It just creates code dynamically at runtime. To put it simply, he is just creating text and having Ruby read it as source code.
Here would be a much simpler version:
eval("class Game_Player; attr_accessor :new_variable; end")
You run that, you will see that you can now set a variable using "$game_
player.new_variable = @something".
Since Ruby is scripted, things aren't precompiled and you can actually build and create classes and variables dynamically and load it into Ruby's memory.
Here's an old little snippet I wrote long ago that does something similar using a metaclass.
# encoding: UTF-8
#==============================================================================
# ** Object
#------------------------------------------------------------------------------
# This class is the greatest ancestor of all Ruby objects.
#==============================================================================
class Object
#----------------------------------------------------------------------------
# * Define and get the object's metaclass
#----------------------------------------------------------------------------
def metaclass
class << self
self
end
end
#----------------------------------------------------------------------------
# * Define attr_accessors for the object
#----------------------------------------------------------------------------
def define_attributes(hash)
hash.each_pair {|key, value|
metaclass.send(:attr_accessor, key)
send("#{key}=".to_sym, value)
}
end
end
This allows for setting a bunch of public instance variables on a object during runtime using a hash of key:value pairs. This is slightly different, though, since using a metaclass only has an effect on the instance, and not the class. The way above will make it so that new instances will have them attributes defined, while the method I posted will not.
Although metaprogramming allows for some cool things, its really not necessary 99% of the time, and can be prone to bugs if you don't implement it correctly. Even the above example just looks like he was making something fancy just to avoid typing out each one of them methods, I don't really see anything dynamic being added, and it even says not to edit.
Here would be an example of doing something dynamically. Say you want the user to be able to create their own actor parameters in addition to the default one, but you want them to be normally accessible methods, and not just an array of values or whatever. You could do this.
# Define your parameters here:
PARAMETERS = ['spd', 'mana', 'sneak']
# Now lets run the code...
PARAMETERS.each {|param|
eval("class Game_Actor; attr_accessor :#{param}; end")
}
actor = Game_Actor.new
actor.sneak = 45
puts actor.sneak