# This is still very abstract. For instance, you'll need to program some
# logic for deciding which children get forwarded requests, etc. Also, I've
# used ( *args, &block ) as parameter/argument lists a lot. You'll want to
# specialize those to your actual usage.

class A
  def initialize
    @b_objs = []
  end

  def add_b( *args, &block )
    @b_objs << B.new( *args, &block )
  end

  # delegation to one of the b_objs
  def b1( *args, &block )
    choose_b( *args, &block ).b1
  end

  def b2( *args, &block )
    choose_b( *args, &block ).b2
  end

  def add_c( *args, &block )
    choose_b_for_c( *args, &block ).add_c( *args, &block )
  end

  def c1( *args, &block )
    choose_b_for_c( *args, &block ).c1
  end

  def c2( *args, &block )
    choose_b_for_c( *args, &block ).c2
  end

  protected
  def choose_b( *args, &block )
    # put logic here for determining which b_obj matches the parameters.
    # Example:
    @b_objs.first
  end

  def choose_b_for_c( *args, &block )
    # put logic here for determining which b_obj contains the c_obj that
    # matches the parameters. Example:
    @b_objs.first
  end
end

class B
  attr_reader :b1, :b2

  def initialize
    @c_objs = []
  end

  def add_c( *args, &block )
    @c_objs << C.new( *args, &block )
  end

  # delegation to one of the c_objs
  def c1( *args, &block )
    choose_c( *args, &block ).c1
  end

  def c2( *args, &block )
    choose_c( *args, &block ).c2
  end

  protected
  def choose_c( *args, &block )
    # put logic here for determining which c_obj matches the parameters.
    # Example:
    @c_objs.first
  end
end

class C
  attr_accessor :c1, c2
end

# Jacob Fugal