Vladimir Agafonkin wrote:
> Hi!
> 
> What is the best way to access class' instance variables from a method
> of another instance variable of the same class that is a class itself?
> :-)
> 
> OK, Let's say I have Duck class with an instance variable
> @quack_behaviour of QuackBehaviour class inside. Duck#quack method
> calls one of the QuackBehaviour methods, and I want to access some of
> the intance variables (say, @name) of the caller Duck object from that
> method.
> 
> One way is to set an attr_accessor :name (or use instance_variable_get)
> and pass "self" as a parameter to the @quack_behaviour method. But it
> seems for me that it is not the most appropriate way of doing this. Or
> is it?

This is a slightly different way, based on a soon-to-be-released version
of MinDI (which is a dependency injection framework and hence the
"inject" terminology):

module Injectable
  module Injected
    def method_missing(*args, &block)
      @__injectable__container__ || super
      @__injectable__container__.send(*args, &block)
    rescue NoInjectedMethodError
      super
    end
  end

  def inject_into obj
    obj.extend Injected
    obj.instance_variable_set(:@__injectable__container__, self)
    obj
  end

  def method_missing(m, *rest)
    raise NoInjectedMethodError
  end
end

class Duck
  include Injectable

  def quack; @quack_behavior.quack; end
  def waddle; @waddle_behavior.waddle; end

  def initialize(h)
    @quack_behavior = h[:quack_behavior]
    @waddle_behavior = h[:waddle_behavior]

    inject_into @quack_behavior
    inject_into @waddle_behavior
  end
end

class StandardQuacker
  def quack
    puts "QUACK!"
  end
end

class NoisyWaddler
  def waddle
    quack       # note that this propagates to Duck then to quacker
    puts "<waddle>"
    quack
  end
end

duck = Duck.new(
  :quack_behavior   => StandardQuacker.new,
  :waddle_behavior  => NoisyWaddler.new
)

duck.waddle

__END__

Output:

QUACK!
<waddle>
QUACK!

-- 
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407