class Hash
  alias orig_each each
  def each(kwd = nil, &block)
    begin
      __send__("each_#{kwd}", &block)
    rescue NoMethodError
      orig_each(&block)
    end
  end
end

if __FILE__ == $0
  require 'test/unit'
  class EachTest < Test::Unit::TestCase
    def setup
      @h = {a: 1, b: 2, c: 3}
    end
    def test_each_key
      e = @h.each(:key)
      assert_instance_of(Enumerator, e)
      assert_equal(:a, e.next)
      assert_equal(:b, e.next)
      assert_equal(:c, e.next)
      ary = []
      @h.each(:key) do |key|
        ary << key
      end
      assert_equal([:a, :b, :c], ary)
    end
    def test_each_value
      e = @h.each(:value)
      assert_instance_of(Enumerator, e)
      assert_equal(1, e.next)
      assert_equal(2, e.next)
      assert_equal(3, e.next)
      ary = []
      @h.each(:value) do |value|
        ary << value
      end
      assert_equal([1, 2, 3], ary)
    end
    def test_each_pair
      e = @h.each(:pair)
      assert_instance_of(Enumerator, e)
      assert_equal([:a, 1], e.next)
      assert_equal([:b, 2], e.next)
      assert_equal([:c, 3], e.next)
      ary = []
      @h.each(:pair) do |value|
        ary << value
      end
      assert_equal([[:a, 1], [:b, 2], [:c, 3]], ary)
    end
    def test_each_entry
      e = @h.each(:entry)
      assert_instance_of(Enumerator, e)
      assert_equal([:a, 1], e.next)
      assert_equal([:b, 2], e.next)
      assert_equal([:c, 3], e.next)
      ary = []
      @h.each(:entry) do |value|
        ary << value
      end
      assert_equal([[:a, 1], [:b, 2], [:c, 3]], ary)
    end
    def test_each
      e = @h.each
      assert_instance_of(Enumerator, e)
      assert_equal([:a, 1], e.next)
      assert_equal([:b, 2], e.next)
      assert_equal([:c, 3], e.next)
      ary = []
      @h.each do |value|
        ary << value
      end
      assert_equal([[:a, 1], [:b, 2], [:c, 3]], ary)
    end
  end
end
