require 'facets/core/kernel/set_from'

module Kernel

  # Assign via setter methods using a hash, associative
  # array or block.
  #
  #   object.set_with( :a => 1, :b => 2 )
  #   object.set_with( :a, 1, :b, 2 )
  #   object.set_with( [:a, 1], [:b, 2] )
  #   object.set_with( *[[:a, 1], [:b, 2]] )
  #   object.set_with{ |s| s.a = 1; s.b = 2 }
  #     
  #
  # These are all the same as doing:
  #
  #   object.a = 1
  #   object.b = 2
  #
  # The array forms gaurentees order of operation.
  #
  # This method does not check to make sure the object
  # repsonds to the setter method. For that see #populate.

  def set_with(*args) #:yield:
    harg = args.last.is_a?(Hash) ? args.pop : {}

    unless args.empty?
      # if not assoc array, eg. [ [], [], ... ]
      # preserves order of opertation
      unless args[0].is_a?(Array)
        i = 0; a = []
        while i < args.size
          a << [ args[i], args[i+1] ]
          i += 2
        end
        args = a
      end
    end

    args.each do |k,v|
      self.send( "#{k}=", v )
    end

    harg.each do |k,v|
      self.send( "#{k}=", v )
    end

    yield self if block_given?

    self
  end

end



#  _____         _
# |_   _|__  ___| |_
#   | |/ _ \/ __| __|
#   | |  __/\__ \ |_
#   |_|\___||___/\__|
#
=begin test

  require 'test/unit'

  class TCKernel < Test::Unit::TestCase

    Customer = Struct.new( "Customer", :name, :address, :zip )

    def test_hash
      bob = Customer.new()
      x = { :name => "Bob Sawyer", :address => "123 Maple, Anytown NC", :zip => 12345 }
      bob.set_with(x)
      assert_equal(x[:name], bob.name)
      assert_equal(x[:address], bob.address)
      assert_equal(x[:zip], bob.zip)
    end

    def test_block
      bob = Customer.new()
      x = lambda {|s| s.name = "Bob Sawyer"; s.address = "123 Maple, Anytown NC"; s.zip = 12345 }
      bob.set_with(&x)
      assert_equal("Bob Sawyer", bob.name)
      assert_equal("123 Maple, Anytown NC", bob.address)
      assert_equal(12345, bob.zip)
    end

  end

=end
