Turning Dwemthy's Array into a mixin

As a beginner, I'm having trouble converting the metaprogramming in
Dwemthy's Array (http://poignantguide.net/dwemthy/) into a convenient
mixin that I can use for many classes. The trouble seems to be the
"def self." declarations, but I'm not too sure; in any
case, .metaclass and .traits don't seem to be mixing in. What should I
change?

Thanks in advance!

module Dwemthy

  def self.metaclass
    class << self; self; end
  end

  def self.traits(*given_traits)
    return @traits if given_traits.empty?

    attr_accessor(*given_traits)

    given_traits.each do |trait|
      metaclass.instance_eval do
        define_method(trait) do |trait_value|
          @traits ||= {}
          @traits[trait] = trait_value
        end
      end
    end

    class_eval do
      define_method(:initialize) do
        self.class.traits.each do |k, v|
          instance_variable_set("@#{k}", v)
        end
      end
    end
  end

end

You might take a look at the metaid gem

Gem install metaid

It contains some of those meta classes - I use it for creating Activerecord
classes on the fly for data driven XML ingestion.

Jamie

···

-----Original Message-----
From: ruby-talk-admin@ruby-lang.org [mailto:ruby-talk-admin@ruby-lang.org]
On Behalf Of rbysamppi@gmail.com
Sent: Tuesday, November 27, 2007 9:35 PM
To: ruby-talk ML
Subject: Turning Dwemthy's Array into a mixin

As a beginner, I'm having trouble converting the metaprogramming in
Dwemthy's Array (http://poignantguide.net/dwemthy/) into a convenient
mixin that I can use for many classes. The trouble seems to be the
"def self." declarations, but I'm not too sure; in any
case, .metaclass and .traits don't seem to be mixing in. What should I
change?

Thanks in advance!

module Dwemthy

  def self.metaclass
    class << self; self; end
  end

  def self.traits(*given_traits)
    return @traits if given_traits.empty?

    attr_accessor(*given_traits)

    given_traits.each do |trait|
      metaclass.instance_eval do
        define_method(trait) do |trait_value|
          @traits ||= {}
          @traits[trait] = trait_value
        end
      end
    end

    class_eval do
      define_method(:initialize) do
        self.class.traits.each do |k, v|
          instance_variable_set("@#{k}", v)
        end
      end
    end
  end

end

Hey, so, yes, this is what Dwemthy has been talking about all along,
this is exactly what caused him to start grinding his teeth and his
blood pressure went through the roof and he got a contagious clubbed
foot and so on, simply because he didn't know or have the slightest
inkling concerning append_features.

Mixins only mix instance methods. However, our friend Nobu Nakada
has just the trick. -> http://redhanded.hobix.com/bits/hyperextended.html

Basically, put all the class methods in their own module. Then mix
the module into the Dwemthy module using `extend`. Then add an
`append_features` method to the Dwemthy module that mixes both into
future mixees. It's a bit of a trip, but still only about five
extra lines of code.

Nobu lays low, but he's filthy smart that one.

_why

···

On Wed, Nov 28, 2007 at 11:35:00AM +0900, rbysamppi@gmail.com wrote:

As a beginner, I'm having trouble converting the metaprogramming in
Dwemthy's Array (http://poignantguide.net/dwemthy/\) into a convenient
mixin that I can use for many classes. The trouble seems to be the
"def self." declarations, but I'm not too sure; in any
case, .metaclass and .traits don't seem to be mixing in. What should I
change?