_why's method allows us to build 'traits' for the character (by calling the
'trait' class method), and the meta programming behind the scenes builds an
'initialize' instance method for the class.
What if I want to build a second method called 'command'? It should place
the argument in an array that can be referenced later. It will need to also
build an initialize method for my class, but one of them will have to be
overwritten.
Does anyone have any smart ways to combine or chain these two initialize
methods together?
I ultimately want to do something like this:
class Dragon < Creature
traits :life
life 100
command :fly
def fly
puts "I am flying..."
end
end
After an instance is created, it will contain the instance variable
'commands', which is an array holding the symbol 'fly'.
Does anyone have any ideas? In the end, I'd be adding more and more of
these commands to my DSL. This is a DSL, right?
_why's method allows us to build 'traits' for the character (by calling the
'trait' class method), and the meta programming behind the scenes builds an
'initialize' instance method for the class.
What if I want to build a second method called 'command'? It should place
the argument in an array that can be referenced later. It will need to also
build an initialize method for my class, but one of them will have to be
overwritten.
Does anyone have any smart ways to combine or chain these two initialize
methods together?
I ultimately want to do something like this:
class Dragon < Creature
traits :life
life 100
command :fly
def fly
puts "I am flying..."
end
end
After an instance is created, it will contain the instance variable
'commands', which is an array holding the symbol 'fly'.
here's something to get you started:
class Creature
def self.command(com) @commands ||= @commands |= [com]
end
def self.commands @commands ||=
end
end
class Dragon < Creature
command :fly
end
p Dragon.commands #=> [:fly]
···
On Sep 3, 2006, at 10:39 PM, Michael Gorsuch wrote:
Does anyone have any ideas? In the end, I'd be adding more and more of
these commands to my DSL. This is a DSL, right?
Sorry I seem to have under estimated what you wanted.
try this instead:
% cat dragon.rb
class Creature
def self.command(cmd)
old_initialize = instance_method(:initialize)
define_method(:initialize) do |*args| @commands ||= @commands |= [cmd]
old_initialize.bind(self).call(*args)
end
end
def commands @commands ||=
end
end
class Dragon < Creature
command :fly
def fly
puts "I'm flying"
end
command :breathe_fire
def breathe_fire
puts "I'm breathing fire!"
end
end
dragon = Dragon.new
p dragon.commands
% ruby dragon.rb
[:breathe_fire, :fly]
···
On Sep 3, 2006, at 10:39 PM, Michael Gorsuch wrote:
What if I want to build a second method called 'command'? It should place
the argument in an array that can be referenced later. It will need to also
build an initialize method for my class, but one of them will have to be
overwritten.
Does anyone have any smart ways to combine or chain these two initialize
methods together?
I ultimately want to do something like this:
class Dragon < Creature
traits :life
life 100
command :fly
def fly
puts "I am flying..."
end
end
After an instance is created, it will contain the instance variable
'commands', which is an array holding the symbol 'fly'.
Does anyone have any ideas? In the end, I'd be adding more and more of
these commands to my DSL. This is a DSL, right?
On 9/3/06, Logan Capaldo <logancapaldo@gmail.com> wrote:
On Sep 3, 2006, at 10:39 PM, Michael Gorsuch wrote:
>
> What if I want to build a second method called 'command'? It
> should place
> the argument in an array that can be referenced later. It will
> need to also
> build an initialize method for my class, but one of them will have
> to be
> overwritten.
>
> Does anyone have any smart ways to combine or chain these two
> initialize
> methods together?
>
> I ultimately want to do something like this:
>
> class Dragon < Creature
> traits :life
> life 100
>
> command :fly
>
> def fly
> puts "I am flying..."
> end
>
> end
>
> After an instance is created, it will contain the instance variable
> 'commands', which is an array holding the symbol 'fly'.
>
> Does anyone have any ideas? In the end, I'd be adding more and
> more of
> these commands to my DSL. This is a DSL, right?
Sorry I seem to have under estimated what you wanted.
try this instead:
% cat dragon.rb
class Creature
def self.command(cmd)
old_initialize = instance_method(:initialize)
define_method(:initialize) do |*args| @commands ||= @commands |= [cmd]
old_initialize.bind(self).call(*args)
end
end
def commands @commands ||=
end
end
class Dragon < Creature
command :fly
def fly
puts "I'm flying"
end
command :breathe_fire
def breathe_fire
puts "I'm breathing fire!"
end
end
Which kind of puts a sticky note on the fridge of the derived class that it
needs to do something, but allows you to put off what you're doing until
you're actually instantiating the object. This way when you get to #do
something, you can do it based on the arguments passed at initialize time,
like say you get dragon=Dragon.new(AmazinglyPowerful) - you can make your
breathe_fire command hot enough to melt sand.
I have also actually been passing code as blocks:
Class Dragon < Creature
command :fly, proc {puts "Lookit me, Mom!"}
end
Which lets you instance_eval the block later in the correct namespace, or
just define the method at runtime with define_method. That can also be used
in combination with a trick I found here on ruby-lang via google to
instance_eval a block with arguments; said trick will soon not be neccesary,
so I'll just add a note to google instance_exec and you'll probably dig it
up fine.
Anyway, I really like the line above that rebinds the initialize method to
perform a kind of 'reverse super'...
old_initialize.bind(self).call(*args)
...and I'm trying to work out if it provides some benefits I have
overlooked, apart from the fact that it will make the initialize method look
a little cleaner and the things like self.command look a little messier.
Cheers,
ben
···
-----Original Message-----
On 9/3/06, Logan Capaldo <logancapaldo@gmail.com> wrote: