Project

General

Profile

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 accessed 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)`)

Back