Issue #14313 has been updated by nobu (Nobuyoshi Nakada).


Shouldn't unspecified attribute raise an exception?

```diff
diff --git c/error.c i/error.c
index 990f9f7855..7870e58035 100644
--- c/error.c
+++ i/error.c
@@ -1692,8 +1692,6 @@ key_err_initialize(int argc, VALUE *argv, VALUE self)
 {
     VALUE message;
     VALUE options;
-    VALUE receiver = Qnil;
-    VALUE key = Qnil;
 
     rb_scan_args(argc, argv, "01:", &message, &options);
 
@@ -1711,16 +1709,13 @@ key_err_initialize(int argc, VALUE *argv, VALUE self)
 	keywords[1] = id_key;
 	rb_get_kwargs(options, keywords, 0, 2, values);
 	if (values[0] != Qundef) {
-	    receiver = values[0];
+	    rb_ivar_set(self, id_receiver, values[0]);
 	}
 	if (values[1] != Qundef) {
-	    key = values[1];
+	    rb_ivar_set(self, id_key, values[1]);
 	}
     }
 
-    rb_ivar_set(self, id_receiver, receiver);
-    rb_ivar_set(self, id_key, key);
-
     return self;
 }
 
diff --git c/test/ruby/test_key_error.rb i/test/ruby/test_key_error.rb
index 852bd32712..fe1d5bb5ab 100644
--- c/test/ruby/test_key_error.rb
+++ i/test/ruby/test_key_error.rb
@@ -15,11 +15,15 @@
     receiver = Object.new
     error = KeyError.new(receiver: receiver)
     assert_equal(receiver, error.receiver)
+    error = KeyError.new
+    assert_raise(ArgumentError) {error.receiver}
   end
 
   def test_key
     error = KeyError.new(key: :key)
     assert_equal(:key, error.key)
+    error = KeyError.new
+    assert_raise(ArgumentError) {error.key}
   end
 
   def test_receiver_and_key
```

----------------------------------------
Feature #14313: Support creating KeyError with receiver and key from Ruby
https://bugs.ruby-lang.org/issues/14313#change-69855

* Author: kou (Kouhei Sutou)
* Status: Closed
* Priority: Normal
* Assignee: matz (Yukihiro Matsumoto)
* Target version: 
----------------------------------------
`KeyError` has readers for error details, `receiver` and `key`. They are convenient to process `KeyError`.

We can set `receiver` and `key` to `KeyError` by `rb_key_err_new()` in C. But we can't set them in Ruby. Because `receiver` and `key` use no `@` instance variables.

How about adding `KeyError#initialize` that accepts `receiver` and `key`? Because `KeyError` is useful in pure Ruby libraries. For example, csv library uses `KeyError`: https://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/lib/csv.rb?revision=59849&view=markup#l321

```ruby
def fetch(header, *varargs)
  # ...
  raise KeyError, "key not found: #{header}"
  # ...
end
```

I want to use `KeyError` for `Hash` like objects such as `Arrow::Table` in [Red Arrow](https://github.com/red-data-tools/red-arrow/).

The attached patch adds `KeyError#initialize` that behaves as the following:

```ruby
p KeyError.new.message
# => "KeyError": No change. Keep backward compatibility.

p KeyError.new("Message").message
# => "Message": No change. Keep backward compatibility.

p KeyError.new(receiver: Object.new).receiver
# => The Object instance.

p KeyError.new(key: :unknown_key).key
# => :unknown_key

key_error = KeyError.new(receiver: Object.new, key: :unknown_key)
p key_error.receiver
# => The Object instance.
p key_error.key
# => :unknown_key

key_error = KeyError.new("Message", receiver: Object.new, key: :unknown_key)
p key_error.message
# => "Message"
p key_error.receiver
# => The Object instance.
p key_error.key
# => :unknown_key
```


---Files--------------------------------
key_error_new.diff (2.91 KB)


-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>