Ruby constants have weird behavior in class_eval

I was playing with some code the other day, and I noticed that constants
work strangely in class_eval blocks. Sometimes it can find the
constant, and sometimes it cannot.

For example, say we have a class with a constant:

class Foo
  CONS = 'const'

Now, if we reopen the class and print the constant, it works as

>> class Foo
>>   puts CONS
>> end

However, if we use a class_eval instead of reopening the class, ruby
cannot find the constant:

>> Foo.class_eval { puts CONS }
NameError: uninitialized constant CONS
        from (irb):12
        from (irb):11:in `class_eval'
        from (irb):11

It gets even stranger. We can still see the constant in the list of

>> Foo.class_eval { puts self.constants }

Furthermore, a const_get still works:

>> Foo.class_eval { puts const_get(:CONS) }

Finally, if we try the class_eval again with a string instead of a
block, it works:

>> Foo.class_eval "puts CONS"

Apparently, constants have a problem with blocks inside of class_eval.

Paul Gross

Paul Gross

I'm a lead software developer in Seattle working for Braintree Payments.

Read More