Can't figure out what's wrong

I'm reading the why's ruby guide, and i've retyped a class in the guide
to use through the metaprogramming chapter. when i try to use it with
irb i get this error:
nomethoderror: undefined method '[]=] for nil:class
from path/dwemthy.rb:18:in 'life'
from path/dwemthy.rb:16:in 'life'
from path/rabbit.rb:4

here's the code for dwemthy.rb:
class Creature

  # get a metaclass for this class
  def self.metaclass; class << self; self; end; end

  # advanced metaprogramming cord for clean traits
  def self.traits( *arr )
    return @traits if arr.empty?

    # 1. setup accessors for each variable
    attr_accessor *arr

    # 2. add a new class method to each trait
    arr.each do |a|
      metaclass.instance_eval do
        define_method( a ) do |val|
          @triats ||= {}
          @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_varable_set("@#{k}", v)
        end
      end
    end

  end

  # creature attributes are read only
  traits :life, :strength, :charisma, :weapon

  # this method applies a hit taken during a fight
  def hit( damage )
    p_up = rand( charisma )
    if p_up % 9 == 7
      @life += p_up / 4
      puts "[#{ self.class } magick powers up #{ p_up }!]"
    end

    # this method takes one turn in a fight
    def fight( enemy, weapon )
      if life <= 0
        puts "[#{ self.class } is too dead to fight!]"
        return
      end

      # attack opponent
      your_hit = rand( strength + weapon )
      puts "[You hit with #{ your_hit } points of damage!]"
      enemy.hit( your_hit )

      # retaliation
      p enemy
      if enemy.life > 0
        enemy_hit = rand( eneme.strenght + enemy.weapon )
        puts "[Your enemy hit with #{ enemy_hit } points \
        of damage!] "
        self.hit( enemy_hit )
      end
    end

  end
end

class DwemthysArray < Array
  alias _inspect inspect
  def inspect; "#<#{ self.class }#{ _inspect }>"; end
  def method_missing( meth, *args )
    answer = first.send( meth, *args )
    if first.life <= 0
      shift
      if empty?
        puts "[Whoa. You decimated Dwemty's Array!]"
      else
        puts "[Get ready. #{ first.class } has emerged.]"
      end
    end
    answer || 0
  end
end

···

--
Posted via http://www.ruby-forum.com/.

here is the code for rabbit.rb:
class Rabbit < Creature
  traits :bobs

  life 10
  strength 2
  charisma 44
  weapon 4
  bombs 3

  # little boomerang
  def ^( enemy )
    fight( enemy, 13 )
  end

  # the hero's sword is unlimited
  def /( enemy )
    fight( enemy, rand( 4+ ( ( enemy.life % 10 ) ** 2 ) ) )
  end

  # lettuce will build your strength and extra ruffage
  # will fly in the face of your opponent
  def %( enemy )
    lettuce = rand( chairsma )
    puts "[Healthy lettuce gives you#( lettuce ) life points!!]"
    @life += lettuce
    fight( enemy, 0 )
  end

  # bombs, but you have only threee
  def *( enemy )
    if @bombs.zero?
      puts '[Out of bombs!]'
      return
    end
    @bombs -= 1
    fight( enemy, 86 )
  end
end

···

--
Posted via http://www.ruby-forum.com/.

Erik, there are some typos in your code. See below.

erik blas schrieb:

I'm reading the why's ruby guide, and i've retyped a class in the guide to use through the metaprogramming chapter. when i try to use it with irb i get this error:
nomethoderror: undefined method '=] for nil:class
from path/dwemthy.rb:18:in 'life'

This means that in line 18, you tried to call method "=" on nil. Nil doesn't have such a method, so the NoMethodError is raised.

from path/dwemthy.rb:16:in 'life'
from path/rabbit.rb:4

here's the code for dwemthy.rb:
class Creature

  # get a metaclass for this class
  def self.metaclass; class << self; self; end; end

  # advanced metaprogramming cord for clean traits
  def self.traits( *arr )
    return @traits if arr.empty?

    # 1. setup accessors for each variable
    attr_accessor *arr

    # 2. add a new class method to each trait
    arr.each do |a|
      metaclass.instance_eval do
        define_method( a ) do |val|
          @triats ||= {}
          @traits[a] = val

This is line 18. It looks like an assignment, but it really is a method call. It calls method "=" on the object @traits with arguments a and val. The error message above means that @traits is nil. If you look at the previous line (line 17), you notice the typo.

        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_varable_set("@#{k}", v)

This should be "instance_variable_set". Note the missing "i".

        end
      end
    end
  end

I haven't looked further. HTH.

Regards,
Pit

Thank you for the help. Guess I'm just tired and didn't notice all the
typos. Was driving me up the wall.

···

--
Posted via http://www.ruby-forum.com/.

When typing in a program that has been provided, typos in Ruby can be
irritating, as you've seen.

When building my own programs, I try to go in smaller bites in Ruby than I might
in C# or Java, because syntax errors and typos are often hard to find.

···

On Tue, 27 Dec 2005 18:52:23 +0900, erik blas <ether.sa@gmail.com> wrote:

Thank you for the help. Guess I'm just tired and didn't notice all the
typos. Was driving me up the wall.

--
Ron Jeffries
www.XProgramming.com
I'm giving the best advice I have. You get to decide if it's true for you.