mrwnt10
mrwnt10

Reputation: 1415

Difference between passing arguments to define_method and to the following block?

I am confused by the following code from Poignant Guide:

# 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

  # Creature attributes are read-only
  traits :life, :strength, :charisma, :weapon
end

The above code is used to create a new class, as in the following:

class Dragon < Creature
  life( 1340 )     # tough scales
  strength( 451 )  # bristling veins
  charisma( 1020 ) # toothy smile
  weapon( 939 )    # fire breath
end

I need to study the basics of meta-programming more on my own, but for now I just want to know, where does the val block argument come from in define_method( a ) do |val|? It represents the point values assigned to each trait, but I don't understand how each of those numbers become a block argument.

Also, why is a passed in the parentheses to define_method, while val is passed in as a block argument?

I've read over this question on the subject of define_method arguments, but it doesn't address the reasons for passing arguments to define_method rather than to the block.

Upvotes: 0

Views: 179

Answers (1)

sawa
sawa

Reputation: 168101

In the form

define_method(:foo){|x| ...}

:foo is the method name and x is the argument. They have different roles. It is the same as:

def foo(x)
  ...
end

Upvotes: 1

Related Questions