Ruby 素振り

class Part
  attr_accessor :parent, :name
  attr_reader :parts
  
  def initialize name
    @name = name
    @parts = {}
  end
  
  def add child
    @parts[child.name] = child
    child.parent = self
    self.instance_eval(%{
       def #{child.name}
        @parts["#{child.name}"]
       end})
  end
end

class PCBuilder
  def build(name="pc", &block)
    def board(name="board", &block) 
      def cpu(name="cpu", &block)
        @cpu = Part.new(name)
        @board.add @cpu
        instance_eval(&block) if block_given?
      end
      
      def hd(name="hard_disk", &block)
        @hd = Part.new(name)
        @board.add @hd
        instance_eval(&block) if block_given?
      end
      
      def memory(name="my_memory", &block)
        @memory = Part.new(name)
        @board.add @memory
        instance_eval(&block) if block_given?
      end
      
      @board = Part.new(name)
      @pc.add @board
      instance_eval(&block) if block_given?
    end
    
    def cover(name="cover", &block)
      @cover = Part.new(name)
      @pc.add @cover
      instance_eval(&block) if block_given?
    end
    
    # # うまく書けない
    # def method_missing(action, *args, &block)
    #   # puts #{args[1]}
    #   eval %{
    #     @#{action.to_s} = Part.new("#{args[0]}")
    #     @pc.add @#{action.to_s}
    #     insrance_eval(&block)  if block_given?
    #   }
    # end
    
    @pc = Part.new name
    instance_exec(@pc, &block) if block_given?
    return @pc
  end
end


pc_builder = PCBuilder.new

pc = pc_builder.build do
  board "my_board" do
    cpu "my_cpu_a"
    cpu "my_cpu_b"
    hd "my_hard_disk"
    memory "my_memory"
  end
  cover "my_cover"
end

require "pp"

puts pc.my_cover.name
puts pc.my_board.my_memory.name
puts pc.my_board.my_cpu_b.name