Search code examples
ruby

How to access class attribute, which was set by class_exec()


This is what I'm trying to do:

class Foo; end

Foo.class_exec do
  class_variable_set(:@@x, 42)
  def get
    @@x # runtime error here!
  end
end

puts Foo.new.get

I'm getting (Ruby 3.2.1):

$ ruby a.rb
a.rb:6:in `get': class variable access from toplevel (RuntimeError)
    from a.rb:10:in `<main>'

How can I read this @@x, which I just set?


Solution

  • There's class_variable_get, but since it's a method of Module, you have to call it on the receiver's class or singleton_class:

    Foo.class_exec do
      class_variable_set(:@@x, 42)
      def get
        self.class.class_variable_get(:@@x)
        # or
        # singleton_class_variable_get(:@@x)
      end
    end
    

    Alternatively, it's perfectly fine in Ruby to re-open a class:

    class Foo; end
    
    class Foo
      @@x = 42
    
      def get
        @@x
      end
    end
    

    Note that it's usually discouraged to use class variables, due to their unexpected inheritance behavior see Why is using a class variable in Ruby considered a 'code smell'?