Read more

The many gotchas of Ruby class variables

Henning Koch
February 12, 2013Software engineer at makandra GmbH

TLDR: Ruby class variables (@@foo) are dangerous in many ways. You should avoid them at all cost. See bottom of this card for alternatives.

Class variables are shared between a class hierarchy

Illustration web development

Do you need DevOps-experts?

Your development team has a full backlog? No time for infrastructure architecture? Our DevOps team is ready to support you!

  • We build reliable cloud solutions with Infrastructure as code
  • We are experts in security, Linux and databases
  • We support your dev team to perform
Read more Show archive.org snapshot

When you declare a class variable, it is shared between this and all descending (inheriting) classes. This is rarely what you want.

Class variables are bound at compile-time

Like unqualified constants, class variables are bound to your current scope when the .rb file is being parsed.
This will probably trip you up when you are writing a module or trait that defines class variables
for other classes.

Say you have the following code:

module Mod
  def foo
    @@foo
  end
end

class Klass
  include Mod
end

@@foo does not mean Klass::@@foo (qualifier added to make my point; it is not valid Ruby expression). It actually means Mod::@@foo and is shared between Mod, all classes including Mod as well as all their subclasses.

Also note that only the class and module keywords can be used to change the scope to which class variables are bound. You can not change scope by using class_eval or instance_eval. For instance, the code below declares a variable @@counter that is shared between all classes of your application:

ActiveRecord::Base.class_eval do
  @@counter = 1
end

When encountering such code, Ruby will warn you:

warning: class variable access from toplevel

Unlike constants, which you can qualify like Klass::CONSTANT, there is no way to qualify a class variable like Klass::@@variable. When you want to tell Ruby that you mean another scope than the current scope, you need to use class_variable_get Show archive.org snapshot and class_variable_set Show archive.org snapshot .

Alternatives to using class variables

Posted by Henning Koch to makandra dev (2013-02-12 17:04)