Bug #19269
Updated by andrykonchin (Andrew Konchin) over 2 years ago
I've noticed a confusing behaviour of `#instance_eval` (and `#instance_exec` as well). In some cases it doesn't see constants defined in the object class.
Examples:
```ruby
C = 1
class A
C = 2
end
```
When `#instance_eval` is called with a String - `A::C` constant is visible, that is pretty expected:
```ruby
A.new.instance_eval("C") # => 2
```
But when it's called with a block - `A::C` isn't visible:
```ruby
A.new.instance_eval { C } # => 1
```
If we define a method that returns a constant (defined in the class), then `A::C` is visible in both cases:
```ruby
C = 1
class A
C = 2
def c; C; end
end
A.new.instance_eval("c") # => 2
A.new.instance_eval { c } # => 2
```
So we see that when `#instance_eval` called with a block and a constant is assessed directly is the only case when a class constant isn't visible.
Wondering whether it's an expected behaviour and the reason to behave this way.
---
In the examples above I've added a top-level declaration `C=1` only for readability. Without this declaration in all the cases when `C` value `1` is returned - a NoName exception is raised (`uninitialized constant C (NameError)`)