#ruby

Ruby 2.5 adds KeyError#receiver and KeyError#key

Atul Bhosale's avatar

Atul Bhosale

Ruby 2.5.0 was recently released.

Earlier to Ruby 1.9 Hash#fetch method would raise IndexError for an invalid key. An IndexError is raised when the given index value is invalid.

irb(main):001:0> hash = { 'foo' => 'bar' }
irb(main):002:0> hash.fetch('foo')
IndexError: key not found
    from (irb):2:in `fetch'
    from (irb):2
    from :0

KeyError class was introduced in Ruby 1.9 and it inherits from IndexError class. It is raised when the specified key is not found.

>> hash = {foo: :bar}
=> {:foo=>:bar}
>> hash.fetch(:baz)
KeyError: key not found: :baz
	from (irb):2:in `fetch'
	from (irb):2
	from /home/atul/.rvm/rubies/ruby-2.4.4/bin/irb:11:in `<main>'

It was proposed that having KeyError#receiver and KeyError#name (or KeyError#key) like NameError, will help to debug and find typo on did_you_mean gem.

begin
  h = {foo: 1, bar: 2}
  h.fetch(:bax)
rescue KeyError => e
  p e.name     #=> :bax
  p e.receiver #=> {foo: 1, bar: 2} equal `h`
  end

There was a discussion about what method name is best between name and key. Benoit Daloze suggested that name is more consistent with other error classes such as NameError#name and NoMethodError#name. Having key as method name was approved.

Ruby 2.5.0

Ruby 2.5.0 provides KeyError#receiver and KeyError#key as methods to return details of receiver object and key which was not found.

begin
  h = { foo: 1, bar: 2}
  h.fetch(:bax)
rescue KeyError => e
  p e.key      #=> :bax
  p e.receiver #=> {foo: 1, bar: 2}
end

I hope these methods are useful in your future debugging attempts.